stringtrimsmalltalkgnu-smalltalk

Why this block is not trimming string


I am trying following block to trim leading spaces from the sent string:

trimleading := [ :str|
    ch := (str byteAt: 1).          "get first character: ERROR HERE"
    ret := str copyFrom: 1.         "make a copy of sent string"
    [ch = ' '] whileTrue: [         "while first char is space"
        ret := (ret copyFrom: 2).   "copy from 2nd char"
        ch := ret byteAt: 1.        "again test first char"
        ].
    ret                             "value is modified string"
].

('>>',(trimleading value: '    this is a test  '),'<<') displayNl.

It works without any error but does not remove leading spaces from the sent string. The return value is identical to sent string.

Apparently, first character ch is not being picked up. at: is also not working instead of byteAt:.

Where is the problem and how can it be solved? Thanks.


Solution

  • The problem is that you are comparing the first element as a byte, which is a not a Character but a number, to a string with one Space character. In Smalltalk integers, characters and strings are different, so you should compare against the corresponding type. In this case you can get the first character of the string with at: instead of byteAt:, or compare to the ascii value of space, which is 32, or Character space asciiValue or $ asciiValue. Here is one possible solution:

        trimleading := [ :str | 
        ch := str at: 1.
        ret := str copyFrom: 1 to: str size.
        [ ch = Character space ]
            whileTrue: [ ret := ret copyFrom: 2 to: ret size.
                ch := ret at: 1 ].
        ret ].
        ^ ('>>' , (trimleading value: '    this is a test  ') , '<<')
            displayNl
    

    as you may have noticed, I changed copyFrom: to copyFrom:to:. This is because, unlike what one would think, copyFrom: doesn't copy from the position passed to the end of the string, but tries to copy the receiver from another object (this behavior is inherited from Object).

    There are quite a few other possible improvements and simplifications to your code, I leave that to you as an exercise.