Ariel Pinchover
Ariel Pinchover

Reputation: 654

Calling self inside a method in smalltalk

I'm trying to do an arithmetic sequence class in smalltalk, I'm having some trouble with doing a printOn method. Here is the code I have, for some reason it would fail upon getting to the self part, I dont understand why though

printOn: aStream
    |i retValue|
    retValue := ''.
    i := 0.
    [i < myCount ] whileTrue: [retValue := retValue + ('', self valueOf: i). i := i -1.].
    aStream nextPutAll: retValue

Upvotes: 3

Views: 356

Answers (2)

Uko
Uko

Reputation: 13386

, is a binary message. It has a higher priority than the valueOf: keyword message. What you are actually executing looks like this:

('', self) valueOf: i

You need to put parenthesis to explicitly tell that you want valueOf: executed first:

'', (self valueOf: i)

secondly:

you do retValue + "probably string". Are you sure that you want to do + in string and not , which is a concatenation?

thirdly:

you start from 0 and decrease i by 1 on each step. Are you sure you will not end up in an infinite loop?

fourthly

why do you need whileTrue:? can't you do something like:

1 to: myCount do: [ :i |
    retValue := retValue + ('', (self valueOf: i - 1)) ]

also please note that it's weird in Smalltalk that your first index is 0 and last is myCount - 1. Usually you start with 1 and end with the size of collection.

fifthly

I've just noticed that you are actually concatenating an empty string with self valueOf: i. That does not make any sense.


In case you just need to print things on the stream do something like:

printOn: aStream
    1 to: myCount do: [ :i |
        aStream nextPutAll: (self valueOf: i) asString) ]

or

printOn: aStream
    (1 to: myCount)
        do: [ :i | aStream nextPutAll: (self valueOf: i) asString) ]
        separatedBy: [ aStream nextPutAll: ', ' ]

I don't know if valueOf: returns a string, if it does, no need to send asString to the result

Upvotes: 10

Euan M
Euan M

Reputation: 1136

Smalltalk has a rigorous precedence order for evaluating messages.

Expressions within parentheses ( ) are evaluated first.
Then Unary messages (messages consisting of an object followed by a message)
Then Binary messages (messages consisting of an object followed by non-alphabetic character followed by another object)
Then Keyword messages - i.e. keyword messages are evaluated last. (Keywords are alphabetic strings ending in a colon, and a keyword message can contain several keywords).
Where precedence is equal, expressions are evaluated from left to right.

In the expression you wrote, the first element evaluated in

  retValue + ( '', self valueOf: i) 

is

 ( '', self valueOf: i)

The first element evaluated within that expression is

 '', self

The result of that then becomes the receiver of the

 valueOf: 1

keyword message.

Incidentally, I would write

i := i - 1

To ensure that anySmalltalk would correctly interpret it as a binary expression, as opposed to i followed by an integer object, -1

Upvotes: 6

Related Questions