Класс и методы для обрезки строки, даже не начиная - PullRequest
1 голос
/ 14 мая 2019

Я пытаюсь создать класс с функциями обрезки строк:

Object subclass: Trimmer [
    trimleading: str [ |ch ret|
        ch := (str first: 1).           "get first character"
        ret := str.                     "make a copy of sent string"
        [ch = ' '] whileTrue: [         "while first char is space"
            ret := (ret copyFrom: 2).   "copy from 2nd char"
            ch := ret first: 1.         "again test first char"
            ].
        ^ret                            "return value is modified string"
        ].
    trim: str [ |ret|
        ret := str. 
        ret := (trimleading value: ret).           "trim leading spaces"
        ret := (trimleading value: (ret reverse)). "reverse string and repeat trim leading"
        ^(ret reverse)                             "return reverse string"
        ]
].

oristr := '        this is a test  '
('ORI..>>',oristr,'<<') displayNl.
('FINAL>>',((Trimmer new) trim: oristr),'<<') displayNl.

Однако он не работает и выдает следующую ошибку:

$ gst trimstring_class.st

trimstring_class.st:10: invalid class body element
trimstring_class.st:17: expected expression

Где проблема и какэто можно решить?

Если я удаляю . после блока метода усечения, как показано в следующем коде:

Object subclass: Trimmer [
    trimleading: str [ |ch ret flag|
        ret := str.                     "make a copy of sent string"
        flag := true.
        [flag] whileTrue: [         "while first char is space"
            ch := ret first: 1.         "again test first char"
            ch = ' '
            ifTrue: [ ret := (ret copyFrom: 2 to: ret size)]    "copy from 2nd char"
            ifFalse: [flag := false] 
            ].
        ^ret                                "value is modified string"
        ]     "<<<<<<< PERIOD/DOT REMOVED FROM HERE."
    trim: str [ |ret|
        ret := str. 
        ret := (trimleading value: ret).           "trim leading spaces"
        ret := (trimleading value: (ret reverse)). "reverse string and repeat trim leading"
        ^(ret reverse)                      "return reverse string"
        ]
].

Затем код запускается, но останавливается со следующей ошибкой:

$ gst trimstring_class.st 
trimstring_class.st:15: undefined variable trimleading referenced
ORI..>>        this is a test  <<
Object: Trimmer new "<0x7f1c787b4750>" error: did not understand #trim:
MessageNotUnderstood(Exception)>>signal (ExcHandling.st:254)
Trimmer(Object)>>doesNotUnderstand: #trim: (SysExcept.st:1448)
UndefinedObject>>executeStatements (trimstring_class.st:23)

Почему метод trimleading сейчас не определен и почему gnu-smalltalk did not understand #trim:?

1 Ответ

1 голос
/ 14 мая 2019

Обычно для такого общего случая целесообразно проверить, реализована ли уже такая функциональность.Вы можете черпать вдохновение для своего кода (вы также станете программистом на Smalltalk).Взгляните на trimBlanksFrom: из sports.st:

 SpStringUtilities class >> trimBlanksFrom: aString [
    "^a String
     I return a copy of aString with all leading and trailing blanks removed."

    <category: 'services'>
    | first last |
    first := 1.
    last := aString size.
    [last > 0 and: [(aString at: last) isSeparator]] 
        whileTrue: [last := last - 1].
    ^last == 0 
        ifTrue: [String new]
        ifFalse: [
            [first < last and: [(aString at: first) isSeparator]] 
                whileTrue: [first := first + 1].
            aString copyFrom: first to: last
       ]
]

Если вы хотите обрезать только начальные пробелы, вы можете просто взять вторую часть, где она обрезает ведущие пробелы.

РЕДАКТИРОВАТЬ Исправлен собственный код OP:

Object subclass: Trimmer [
    trimleading: str [ |ch ret flag|
        ret := str.                     "make a copy of sent string"
        flag := true.
        [flag] whileTrue: [         "while first char is space"
            ch := ret first: 1.         "again test first char"
            ch = ' '
            ifTrue: [ ret := (ret copyFrom: 2 to: ret size) ]    "copy from 2nd char"
            ifFalse:  [flag := false ] 
            ].
        ^ret                                "value is modified string"
        ]     "<<<<<<< PERIOD/DOT REMOVED FROM HERE."
    trim: str [ |ret|
        ret := str. 
        ret := self trimleading: (ret copy).           "trim leading spaces"
        ret := self trimleading: (ret copy reverse). "reverse string and repeat trim leading"
        ^ (ret reverse)                      "return reverse string"
        ]
].

oristr := '        this is a test  '
('ORI..>>',oristr,'<<') displayNl.
('FINAL>>',((Trimmer new) trim: oristr),'<<') displayNl.

Были некоторые ошибки, которые необходимо было исправить.Если вы хотите обратиться к селектору #trimleading:, вы должны использовать ключевое слово self, которое ищет локальный класс (для собственных классов или унаследованных).Далее вам не следует изменять переменную, которую вы присваиваете, следует использовать #copy, иначе можно ожидать странного результата.

...