result := String new.
1 to: 10 do: [:n | result := result, n printString, ’ ’].
smalltalk中的所有内容都是一个对象,对象通过消息进行交互。
我无法理解上面的代码如何理解消息:do:
如何将块从1迭代到10?怎么知道它必须多次重复阻塞?
有人可以解释引擎盖下发生的事情吗?
所有Smalltalk消息都遵循<receiver> <message>.
模式。在这种情况下,接收器是1
(Number
的子实例),消息是to:do:
。
你可以浏览类Number
并在那里看到to:do:
的实现:
to: stop do: aBlock
| nextValue |
nextValue := self.
[nextValue <= stop]
whileTrue:
[aBlock value: nextValue.
nextValue := nextValue + 1]
在你的例子中,stop
是10
而aBlock
是[:n | result := result, n printString, ’ ’]
。事实上,它正在反复向value:
发送aBlock
。
现在,除此之外,许多Smalltalks在看到for:to:
消息时会生成特殊的字节代码,但这只是一个优化。
考虑一下方法
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的常规消息。优化不应该模糊您的思维需要遵循的语义。