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

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

我正在尝试解决 Smalltalk 中的 AoC 问题 12 第 2 部分。具体不是超级相关,但这是我用于解决问题的模型的一维版本的相关部分:

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.

正如变量名称可能暗示的那样,我无法完成检查数字是否等于零 第二个数字是否等于第三个数字的高度复杂的任务。对这条语句进行再多的重构似乎也无法改变最终结果:

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)

(self kin == 0) 收到的 #Value 是什么,为什么不是 True,我该如何解决?

and: 消息的参数必须是 Block(而您传递的是 Boolean)。只需像这样更改您的代码

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

你也可以写得更简洁

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

但是,当然,这是次要的。请注意,我使用了 = 而不是 ==,因为两者的语义略有不同,并且您在这些测试中不需要对象身份(即使 == 在您的例)。


为了完整起见,让我提一下 布尔值的方法:二进制消息 & 就是这样做的。所以,你可以写

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

Smalltalk 语法的优先规则允许您删除 self kinetic = 0 周围的括号,因为这里的主要消息是 =,它也是二进制的。 Xin = X 周围的括号不能删除,否则 & 将优先于最后出现的 =.