无法在 GNU Smalltalk 中调用 "function"

Can not call "function" in GNU Smalltalk

我想定义block并这样调用:

add := [ :a :b |
    ^(a+b).
].

n := add value: 1 value: 2.

但是当我尝试的时候,我得到一个错误:

$ gst 3.1.st 
Object: 3 error: return from a dead method context
SystemExceptions.BadReturn(Exception)>>signal (ExcHandling.st:254)
SystemExceptions.BadReturn class(Exception class)>>signal (ExcHandling.st:151)
SmallInteger(Object)>>badReturnError (Object.st:1389)
UndefinedObject>>executeStatements (3.1.st:3)

如何在 GNU Smalltalk 中调用函数?

好吧,我删除了 return 语句,这段代码工作正常。但是当我尝试定义更复杂的函数时,例如:

nod := [ :a :b |
    (a=b) ifTrue: [a].
    (a>b) ifTrue: [nod value: (a-b) value: b].
    (a<b) ifTrue: [nod value: a value: (b-a)].
].

n := nod value: 1 value: 2.
n printNl.

它打印 nil。如果我用 "early exit":

定义
nod := [ :a :b |
    (a=b) ifTrue: [^a].
    (a>b) ifTrue: [nod value: (a-b) value: b].
    (a<b) ifTrue: [nod value: a value: (b-a)].
].

n := nod value: 1 value: 2.
n printNl.

它给了我同样的错误:return from a dead method context。

我是这样解决这个问题的:

nod := [ :a :b |
    (a=b) ifTrue: [
        a
    ] ifFalse: [
        (a>b) ifTrue: [nod value: (a-b) value: b] ifFalse: [nod value: a value: (b-a)].
    ]
].

n := nod value: 1 value: 2.
n printNl.

但我认为,这不是很美的方式。

删除块内的非本地 return (^)、括号和句点。然后再试一次。

从您的代码中删除 return 语句 (^),它将正常工作。

在smalltalk中,returning退出出现return语句的方法。它用于提前退出,例如 a < b ifTrue: [^a] ifFalse:[^b].

在这种情况下,您不希望该块退出包含方法,您只希望它在发送时计算出某些东西 value:value:。一个块的计算结果是其中的最后一条语句,因此只需将其设为常规语句即可。

顺便说一下,您收到的错误消息也解释了问题:您正试图从一个已经失效的方法中 return 3

您已经接受了原始问题的答案,然后重新定义了您的问题。

要回答您更新后的问题,您可以使用块 returns 其最后一条语句的值这一事实,并使用局部变量:

nod := [ :a :b | |r|
    (a = b) ifTrue: [r := a].
    (a > b) ifTrue: [r := nod value: (a-b) value: b].
    (a < b) ifTrue: [r := nod value: a value: (b-a)].
    r
].

不过,我对上下文很好奇。我怀疑将 class 定义为 selector/method 可能更合适。


顺便说一句,如果任一参数为负,上述实现将进入无限递归。

获得所需结果的最简单方法是:

nod := [ :a :b | a gcd: b ].

:)