1

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?

badp
  • 11,409
  • 3
  • 61
  • 89
  • I'm asking on stack overflow how to and two booleans together. This might just be the lowest point of my career – badp Dec 12 '19 at 14:13
  • No, inlining `kinetic` to say `killmeNow := (XX == 0).` doesn't change things. – badp Dec 12 '19 at 14:15
  • it should be noted that `(self kin == 0) and: (X == Xin) inspect.` does tell me I'm dealing with a `True`... – badp Dec 12 '19 at 14:29

1 Answers1

2

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 =.

Leandro Caniglia
  • 14,495
  • 4
  • 29
  • 51
  • Yeah, my original writing of the condition was terser, then I started desperately adding parentheses to try and get the thing to work... – badp Dec 12 '19 at 14:46