Small talk的消息如何:do:在幕后实施?

问题描述 投票:1回答:2
result := String new. 
1 to: 10 do: [:n | result := result, n printString, ’ ’]. 

smalltalk中的所有内容都是一个对象,对象通过消息进行交互。

我无法理解上面的代码如何理解消息:do:

如何将块从1迭代到10?怎么知道它必须多次重复阻塞?

有人可以解释引擎盖下发生的事情吗?

smalltalk
2个回答
7
投票

所有Smalltalk消息都遵循<receiver> <message>.模式。在这种情况下,接收器是1Number的子实例),消息是to:do:

你可以浏览类Number并在那里看到to:do:的实现:

to: stop do: aBlock | nextValue | nextValue := self. [nextValue <= stop] whileTrue: [aBlock value: nextValue. nextValue := nextValue + 1]

在你的例子中,stop10aBlock[:n | result := result, n printString, ’ ’]。事实上,它正在反复向value:发送aBlock

现在,除此之外,许多Smalltalks在看到for:to:消息时会生成特殊的字节代码,但这只是一个优化。


1
投票

考虑一下方法

m
  1 to: 10 do: [:i | self doSomethingWith: i]

以下是Pharo生成的字节码

    pushConstant: 1                   ; i := 1
    popIntoTemp: 0                    ;
@2: pushTemp: 0                       ; i <= 10 ?
    pushConstant: 10                  ;
    send #'<='                        ;
    jumpFalse: @1                     ; if false, go to end
    self                              ; self doSomethingWith: i
    pushTemp: 0                       ;
    send #doSomethingWith:            ;
    pop                               ; 
    pushTemp: 0                       ; i := i + 1
    pushConstant: 1                   ;
    send #'+'                         ;
    popIntoTemp: 0                    ;
    jumpTo: @2                        ; loop
@1: returnSelf

你可以看到消息#to:do永远不会被发送,而#'<='#+是(尽管它们不在源代码中!)。为什么?由于Bert在他的回答中所说的:这些消息由Smalltalk编译器优化。在Pharo的情况下,优化发生在#to:do:。在其他方言中,#to:do:是用#whileTrue:实现的,#to:do:是经过优化的方法。

一旦你理解了它是如何在引擎盖下工作的,回过头来想想它就像1是接收器10和参数[:i | self doSomethingWith: i]和块qazxswpoi的常规消息。优化不应该模糊您的思维需要遵循的语义。

© www.soinside.com 2019 - 2024. All rights reserved.