首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这段代码将变量a设置为9?

为什么这段代码将变量a设置为9?
EN

Stack Overflow用户
提问于 2019-06-15 22:10:11
回答 2查看 101关注 0票数 2

我对这段代码感到困惑:

代码语言:javascript
复制
| 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,在不影响其奇偶性的情况下从a减去2c不会调用b,因为如果我对块的理解是正确的,则返回块的最后一个元素而不是求值;因此c将返回b,但是timesRepeat丢弃任何返回的内容,因此c中的b没有任何效果。

我的假设被证明是错误的:这段代码将a设置为9。为了了解发生了什么,我稍微修改了这段代码:

代码语言:javascript
复制
| 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

这就是要打印的东西:

代码语言:javascript
复制
1-1012345678

那么,b 到底叫还是?我的假设是b被返回而不是被调用,这是错误的吗?

让我们试着检查一下:

代码语言:javascript
复制
jkl := [Transcript show: 'I am called too.'].
asdf := [Transcript show: 'I am called!'. jkl].

10 timesRepeat: asdf

不,asdf没有在这里调用jkl

代码语言:javascript
复制
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,那么它的效果将是有效地从a中减去1;但这是不可能的。相反,第一次迭代似乎调用了c,然后神秘地,每次迭代似乎都调用了b,即使a是奇怪的!

这里发生了什么事??

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-15 23:49:35

timesRepeat:选择器需要一个块作为参数。您使用括号内的表达式调用它:

代码语言:javascript
复制
10 timesRepeat: (a even ifTrue: b ifFalse: c).

然而,正是这样,c被定义为块[a := a - 2. b],它返回b的值,正好是一个块。因此,timesRepeat:很高兴,它在每次迭代( a是奇数)上执行块b。如果您正确地将它写成:

代码语言:javascript
复制
10 timesRepeat: [a even ifTrue: b ifFalse: c].

最后,a将达到预期的-19。

关于您的声明:如果我对块的理解是正确的,则返回块的最后一个元素而不是求值,但情况并非如此。对于块中的最后一条语句,除了它的结果实际上在执行该块时返回该块的值外,没有任何特殊处理。块中的最后一条语句只是变量的名称。变量的值恰好是一个块,但是不管它是什么,在Smalltalk中只有一个变量名作为语句返回变量的值。如果变量恰好是块,则得到块。没有执行块。

考虑以下几个方面:

代码语言:javascript
复制
[a := 1. b := 2. c := a+b]

执行此块时,a的值为1,b为值2,c为值3,块返回的值为c的值,即3。

代码语言:javascript
复制
[a := 1. b := 2. a]

如果执行此块,结果将是a的值,即1。

代码语言:javascript
复制
[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的结果。

票数 8
EN

Stack Overflow用户

发布于 2019-06-17 02:11:24

也许只有我一个人,但我觉得下面的第二句话有点模糊:

然而,正是这样,c被定义为块a := a-2.b,它返回b的值,而这恰好是块。因此,timesRepeat:是愉快的,它在每个迭代中执行块b,其中a是奇数的。

Smalltalk的语义是:

  1. 评估接收者
  2. 评估论点
  3. 发送消息

这个顺序是至关重要的,因为评估可能有副作用。

所以,实际发生的是:

  1. 接收机10计算为10
  2. 参数a even ifTrue: b ifFalse: c的计算结果为b。副作用a = -1
  3. 发送消息10 timesRepeat: b10 timesRepeat: [a := a + 1]

因此,a = 9

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56614528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档