闲聊的讯息:在幕后如何执行:

时间:2018-09-10 19:11:38

标签: smalltalk

result := String new. 
1 to: 10 do: [:n | result := result, n printString, ’ ’]. 
  

smalltalk中的所有内容都是一个对象,并且这些对象通过   消息。

我不明白上面的代码如何理解to:do的消息:

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

有人可以解释幕后发生的事情吗?

2 个答案:

答案 0 :(得分: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]

在您的示例中,stop10,而aBlock[:n | result := result, n printString, ’ ’]。因此的确,它是在向value:重复发送aBlock

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

答案 1 :(得分: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和参数{{1 }}和块[:i | self doSomethingWith: i]。优化不应掩盖您的思维必须遵循的语义。