Is it possible to pass a block statement as a block argument for a given depth k? For example, if k = 1, I have f(x) defined as [x + 3]
, but if k=2, I want f(f(x)), which is [[x + 3] + 3]
. This is for an assignment, so I am required to use a block statement. #value:
seems to only take integers, is there a more general version of #value:
?
EDIT: Let me be a little clearer. My function takes a range from a to b, and a depth k. The function will evaluate on a block statement. So, for [x + 3] method: 1 to: 3 for: 2
will evaluate [[x+3] + 3]
from 1 to 3. I can evaluate from 1 to 3 just fine whenever k = 1. I'm trying to modify the block statement [x+3]
into [[x+3]+3]
, and that's where I'm running into trouble. I've tried
tempvariable := self "where self is the block statement [x+3]"
tempvariable := tempvariable value: self
but I'm getting a
BlockClosure(Object)>>doesNotUnderstand: #adaptToNumber:andSend:
error (which is why I thought it was integer only)
If I understand your question correctly, you want a method (you named it #method:to:for:
)
that creates and evaluates a block based on an initial block.
As in
[:x | x + 3] method: 1 to: 3 for: 1.
becomes
1 to: 3 do: [:index| [:x | x + 3] value: index].
and evaluates [:x | x + 3]
three times; and
[:x | x + 3] method: 1 to: 3 for: 2.
becomes
1 to: 3 do: [:index| [:y | ([:x | x + 3] value: y) + 3] value: index].
It is not possible to achieve this by modifying an existing block. However, we can try to solve that problem in another way.
Let's write your function and block differently:
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"
For depth k, just invoke the block of k-1 on the result of the original block.
So, a solution can look like
BlockClosure>>depth: k
| closure |
closure := self.
k timesRepeat: [ | newClosure |
newClosure := closure.
closure := [:x | newClosure value: (self value: x)]].
^ closure
and you can invoke it like this:
([:x | x + 3] depth: 0) value: 1. "=> 4"
([:x | x + 3] depth: 1) value: 1. "=> 7"
([:x | x + 3] depth: 2) value: 1. "=> 10"
Adapt to your needs.