我对这段代码感到困惑:
| a b c| a := 1. b := [a := a + 1]. c := [a := a - 2. b].
10 timesRepeat: (a even ifTrue: b ifFalse: c). a
我的假设是这段代码会将a
设置为-19
。每次迭代都会测试a
是否为偶数,但是a
将是奇数,因此将调用c
,并从2
中减去a
而不会影响其奇偶性。 c
不会调用b
,因为如果我对块的理解正确,则将返回块的最后一个元素,而不是求值;因此c
将返回b
,但是timesRepeat
会丢弃返回的任何内容,因此b
中的c
无效。
事实证明,我的假设是错误的:这段代码将a
设置为9
。为了查看发生了什么,我对这段代码做了一些修改:
| a b c| a := 1. b := [Transcript show: (a displayString). a := a + 1]. c := [Transcript show: (a displayString). a := a - 2. b.].
10 timesRepeat: (a even ifTrue: b ifFalse: c). a
这是打印出来的内容:
1-1012345678
所以看来b
是 被调用了吗?我的假设是否错误,即返回b
而不是调用?
让我们尝试检查一下:
jkl := [Transcript show: 'I am called too.'].
asdf := [Transcript show: 'I am called!'. jkl].
10 timesRepeat: asdf
不是,asdf
在这里没有呼叫jkl
:
I am called!I am called!I am called!I am called!I am called!I am called!I am called!I am called!I am called!I am called!
无论如何,如果c
始终只是调用b
,则其效果是有效地从1
中减去a
;但这不会发生。取而代之的是,第一次迭代似乎调用了c
,然后神秘地,即使b
是奇数,每次迭代似乎都调用了a
!
这是怎么回事?
答案 0 :(得分:8)
timesRepeat:
选择器想要一个块作为参数。您正在用括号内的表达式来调用它:
10 timesRepeat: (a even ifTrue: b ifFalse: c).
尽管如此,c
被定义为块[a := a - 2. b]
,该块返回b
的值,并且恰好是一个块。因此timesRepeat:
很高兴,并且它在b
为奇数的每次迭代中执行块a
。如果正确编写为:
10 timesRepeat: [a even ifTrue: b ifFalse: c].
然后最后,a
将为-19。
关于您的陈述:如果我对块的理解是正确的,则返回块的最后一个元素而不是求值,实际上并非如此。块中的最后一条语句没有特殊处理,除了它的结果确实在执行该块时作为该块的值返回之外。您在块中的最后一条语句只是变量的名称。变量的值恰好是一个块,但是无论它是什么,只要在Smalltalk中仅具有一个变量名作为语句就可以返回变量的值。如果变量恰好是一个块,则可以得到该块。该块未执行。
请考虑以下块:
[a := 1. b := 2. c := a+b]
执行此块时,a
的值为1,b
的值为2,c
的值为3。该块将返回的值为c
,即3。
[a := 1. b := 2. a]
如果执行此块,结果将是a
的值为1。
[a := 1. b := 2. c := [a+b]. c]
如果执行此块,结果将是变量c
所代表的块。它不执行块c
。这与前面的示例一致。
因此,当您执行块[Transcript show: 'I am called!'. jkl].
时,将不执行末尾的jkl
。它的值刚刚返回。如果要执行它,则可以编写asdf := [Transcript show: 'I am called!'. jkl value].
,在发送value
消息时将执行一个块。执行块[Transcript show: 'I am called!'. jkl value].
的结果将是执行块jkl
的结果。
答案 1 :(得分:2)
我可能是唯一的一个,但是我发现下面的第二句话有些晦涩:
尽管如此,但是c定义为块[a:= a-2。b],该块返回b的值并且恰好是一个块。 So timesRepeat:很高兴,并且它在每次是奇数的迭代中执行块 b 。 / p>
Smalltalk的语义是:
顺序很关键,因为评估可能会有副作用。
所以,实际发生的是:
10
的评估结果为10
a even ifTrue: b ifFalse: c
的值为b
。副作用a = -1
。10 timesRepeat: b
或10 timesRepeat: [a := a + 1]
因此,a = 9
。