gaa*_*kam 2 variables loops smalltalk parity
我对这段代码感到困惑:
| a b c| a := 1. b := [a := a + 1]. c := [a := a - 2. b].
10 timesRepeat: (a even ifTrue: b ifFalse: c). a
Run Code Online (Sandbox Code Playgroud)
我的假设是这段代码将设置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
Run Code Online (Sandbox Code Playgroud)
这是打印出来的内容:
1-1012345678
Run Code Online (Sandbox Code Playgroud)
如此看来毕竟b
被称为?我的假设是错误的,b
它返回而不是调用吗?
让我们尝试检查一下:
jkl := [Transcript show: 'I am called too.'].
asdf := [Transcript show: 'I am called!'. jkl].
10 timesRepeat: asdf
Run Code Online (Sandbox Code Playgroud)
不,这里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!
Run Code Online (Sandbox Code Playgroud)
不管怎样,如果c
总是只调用b
,其效果将是有效的。减去1
从a
; 但这不会发生。取而代之的是,第一次迭代似乎在调用c
,然后,神秘地,每次迭代似乎都在调用b
,即使a
是奇怪的!
这里发生了什么??
所述timesRepeat:
选择器想要一个块作为一个参数。您使用括号内的表达式来调用它:
10 timesRepeat: (a even ifTrue: b ifFalse: c).
Run Code Online (Sandbox Code Playgroud)
但是,恰好发生这种情况,它c
被定义为[a := a - 2. b]
返回值的块,b
并且恰好是一个块。所以timesRepeat:
很高兴,并且它b
在每次迭代中a
都执行奇数的块。如果正确编写为:
10 timesRepeat: [a even ifTrue: b ifFalse: c].
Run Code Online (Sandbox Code Playgroud)
然后最后,a
将是预期的-19。
关于您的陈述:如果我对块的理解是正确的,那么将返回块的最后一个元素,而不是评估结果,实际上不是这种情况。对块中的最后一条语句没有特殊处理,除了它的结果确实在执行该块时作为该块的值返回之外。您在块中的最后一条语句只是变量的名称。变量的值恰好是一个块,但无论它是什么,只要在Smalltalk中仅具有一个变量名作为语句就可以返回该变量的值。如果变量恰好是一个块,则可以得到该块。该块不执行。
考虑以下块:
[a := 1. b := 2. c := a+b]
Run Code Online (Sandbox Code Playgroud)
执行此块时,a
它将具有值1,b
值2和c
值3。该块将返回的值是的值c
,即3。
[a := 1. b := 2. a]
Run Code Online (Sandbox Code Playgroud)
如果执行此块,结果将是的值a
,即1。
[a := 1. b := 2. c := [a+b]. c]
Run Code Online (Sandbox Code Playgroud)
如果执行此块,则结果将是变量c
代表的块。它不执行块c
。这与先前的示例一致。
所以,当你执行块[Transcript show: 'I am called!'. jkl].
,将jkl
在年底不执行。它的值刚刚返回。如果要执行它,则可以编写asdf := [Transcript show: 'I am called!'. jkl value].
一个A块,该块将在发送value
消息时执行。执行块[Transcript show: 'I am called!'. jkl value].
的结果将是执行块的结果jkl
。
归档时间: |
|
查看次数: |
92 次 |
最近记录: |