Smalltalk:使用块作为块参数?

时间:2013-04-23 01:46:49

标签: arguments block smalltalk function-composition

是否可以将块语句作为给定深度k的块参数传递?例如,如果k = 1,我将f(x)定义为[x + 3],但如果k = 2,我想要f(f(x)),即[[x + 3] + 3]。这是一个赋值,所以我需要使用块语句。 #value:似乎只采用整数,是否有#value:更通用的版本?

编辑:让我更清楚一点。我的函数的范围从a到b,深度为k。该函数将在块语句中进行评估。因此,[x + 3] method: 1 to: 3 for: 2将从1到3评估[[x+3] + 3]。只要k = 1,我就可以从1到3进行评估。我正在尝试将块语句[x+3]修改为{ {1}},那就是我遇到麻烦的地方。我试过了

[[x+3]+3]

但是我得到了 tempvariable := self "where self is the block statement [x+3]" tempvariable := tempvariable value: self 错误(这就是为什么我认为它只是整数)

1 个答案:

答案 0 :(得分:4)

如果我正确理解您的问题,您需要一个方法(您将其命名为#method:to:for:) 根据初始块创建和评估块。

[:x | x + 3] method: 1 to: 3 for: 1. 

变为

1 to: 3 do: [:index| [:x | x + 3] value: index].

并评估[:x | x + 3]三次;和

[:x | x + 3] method: 1 to: 3 for: 2. 

变为

1 to: 3 do: [:index| [:y | ([:x | x + 3] value: y) + 3] value: index].

通过修改现有块可以实现 。但是,我们可以尝试以另一种方式解决这个问题。

让我们编写你的函数并以不同方式阻止:

function                           block                    
f(x) = x + 3                       f := [:x | x + 3]. 
     ↪ f(1) = 4                        ↪ f value: 1 "=> 4"

f₁(x) = f(x)                       f1 := [:x | f value: x].
     ↪ f₁(1) = f(1) = 4                ↪ f1 value: 1 "=> 4"

f₂(x) = f(f(x)) = f₁(f(x))         f2 := [:x | f1 value: (f value: x)].
     ↪ f₂(1) = f₁(4) = 7               ↪ f2 value: 1 "=> 7"

f₃(x) = f(f(f(x))) = f₂(f(x))      f3 := [:x | f2 value: (f value: x)].
     ↪ f₃(1) = f₂(4) = f₁(7) = 10       ↪ f3 value: 1 "=> 10"

对于深度k,只需在原始块的结果上调用k-1块。


解决方案

因此,解决方案可能看起来像

BlockClosure>>depth: k
    | closure |
    closure := self.
    k timesRepeat: [ | newClosure |
        newClosure := closure.
        closure := [:x | newClosure value: (self value: x)]].
    ^ closure

你可以像这样调用它:

([:x | x + 3] depth: 0) value: 1. "=> 4"
([:x | x + 3] depth: 1) value: 1. "=> 7"
([:x | x + 3] depth: 2) value: 1. "=> 10"

适应您的需求。