Smalltalk有封闭吗?

Eon*_*nil 6 closures smalltalk

如果它有闭包,我可以假设我可以在那里使用许多强大的功能样式技术吗?

Luk*_*gli 8

是的,Smalltalk有封闭.以下代码创建一个闭包,返回其两个参数的总和:

sum := [ :a :b | a + b ].
Run Code Online (Sandbox Code Playgroud)

闭包是可以实例化,传递和操纵的对象.为了评估您发送关闭value,value:,value:value:,...

sum value: 1 value: 2.
Run Code Online (Sandbox Code Playgroud)

闭包突出地用于集合以迭代,过滤,映射......集合的所有值:

aCollection select: [ :each | each isOdd ].
aCollection inject: 0 into: [ :each :result | each + result ].
Run Code Online (Sandbox Code Playgroud)

此外,它们用于控制结构,如循环:

[ iterator hasNext ]
    whileTrue: [ iterator next ].
1 to: 10 do: [ :each | ... ].
Run Code Online (Sandbox Code Playgroud)

还使用闭包实现了条件:

condition
   ifTrue: [ do this ]
   ifFalse: [ do that ]
Run Code Online (Sandbox Code Playgroud)


dan*_*lei 6

Pharo有他们:

所有VM都具有最新映像所需的关闭支持

makeAdder := [ :x | [ :y | x + y ]].
add2 := makeAdder value: 2.
add2 value: 3.
Run Code Online (Sandbox Code Playgroud)

退货5.

但请注意

makeCounter := [ :init | [ init := init + 1. init ]].
Run Code Online (Sandbox Code Playgroud)

不会Cannot store into ->init …像(例如)在CL中那样工作():

CL-USER> ((lambda (init) (lambda () (incf init))) 0)
#<COMPILED-LEXICAL-CLOSURE #xC7A495E>
CL-USER> (funcall *)
1
CL-USER> (funcall **)
2
CL-USER> (funcall ***)
3
Run Code Online (Sandbox Code Playgroud)

如果我没有弄错,这在引入新的闭包编译器之前就已经工作了.我不确定为什么它不适用于新的编译器.

  • 块和方法参数在Smalltalk中是只读的.一些古老的编译器没有正确检查块参数写入. (4认同)