Search code examples
gnu-smalltalk

Object: true error: did not understand #value while anding booleans together


I'm attempting to solve AoC problem 12 part 2 in Smalltalk. The specific aren't super relevant, but here's the relevant portion of a single-dimensional version of the model I'm using for the problem:

Object subclass: Moon [
    | X XX Xin |
    init [
        X := 0. XX := 0. Xin := 0.
    ]
    Moon class >> new [ | moon | moon := super new. moon init. ^moon]
    x: xx [ 
        X := xx. XX := 0. Xin := xx.
    ]
    kinetic [ ^ (XX abs) ]
    initialState [ | killmeNow |
        killmeNow := ((self kinetic) == 0).
        killmeNow := killmeNow and: (Xin == X).
        ^killmeNow
    ]
]

moonA := Moon new.
moonA x:  1.
moonA initialState printNl.

As the variable names just might suggest, I'm failing at the highly complex task of checking if a number equals zero and a second number equals a third number. No amount of refactoring of this statement seems to change the ultimate outcome:

Object: true error: did not understand #value
MessageNotUnderstood(Exception)>>signal (ExcHandling.st:254)
True(Object)>>doesNotUnderstand: #value (SysExcept.st:1448)
True>>and: (True.st:116)
Moon>>initialState (omg.st:15)
UndefinedObject>>executeStatements (omg.st:22)

What is the #Value that (self kin == 0) is receiving, why is it not True, and how do I fix this?


Solution

  • The argument of the and: message must be a Block (and you are passing a Boolean). Just change your code like this

     killmeNow := killmeNow and: [Xin == X].   "squared brackets rather that parentheses"
    

    You could also have written the same more succinctly as

      initialState [
         ^self kinetic = 0 and: [Xin = X]
        ]
    

    but, of course, this is secondary. Note that I've used = instead of == because both have a slightly different semantics and you don't need object identity in these tests (even though == will work as well in your case).


    For the sake of completeness, let me mention that there is way to and Booleans: the binary message & does that. So, you could have written

        ^(self kinetic = 0) & (Xin = X).
    

    The precedence rules of the Smalltalk syntax allow you to remove the parentheses around self kinetic = 0 because here the main message is = which is also binary. The parantheses aroung Xin = X cannot be removed, otherwise & would take precedence over the last occurrence of =.