Search code examples
smalltalkgnu-smalltalk

How to concatenate a string in a do block?


I'm trying to go though a array and add characters from that array to another object. The problem is I keep getting a error "Instances of character are not indexable". However when I run tag := tag,char outside of the do block then it works.

|data startTag tag|.
data := '123456778'
startTag := false.
tag := ''.
data asArray do: [:char |
     tag := tag,char] 

Solution

  • The , is defined as

    Collection>>, aCollection
    ^self copy addAll: aCollection; yourself
    

    so that tries to operate on your single character as if it were a collection. That explains the error.

    For larger collections you do not want to build up using , because of the copy that happens each time. Therefore use the streaming protocol:

    |data tag|
    data := '123456778'.
    tag := String streamContents: [:s |
        data do: [ :char |
        s nextPut: char]]
    

    Also take a look at Collection>>do:separatedBy: to add separators between your data.

    [edit] Ah, ok, that's something like

    |data tag tags state|
    data := '<html>bla 12 <h1/></html>'.
    state := #outside.
    tags := OrderedCollection new.
    tag := ''.
    data do: [ :char |
        state = #outside ifTrue: [
            char = $< ifTrue: [ 
                state := #inside.
                tag := '' ]]
        ifFalse:  [ 
             char = $> ifTrue: [ 
                state := #outside.
                tags add: tag] 
            ifFalse: [ tag := tag, (char asString)]]].
    tags
    
    "an OrderedCollection('html' 'h1/' '/html')"