Not a question or anything… I just wanted to share this snippet with
any non-computer-scientist who thinks this is cool
I come from very much an imperative programming background - originally
machine code. Computer science books tend to use LISP, and I find
anything
other than the simplest example to be impenetrable. However, translating
them to Ruby makes it much clearer to me what’s going on.
Simple start: implement the ‘times’ iterator recursively, applied
to an explicit proc argument rather than an implicit block.
def my_times(n, f)
if n >= 1
f.call()
my_times(n-1, f)
end
end
my_times(3, proc { puts “testing” } )
OK, now implement the ‘times’ iterator as an anonymous function (proc)
times = proc { |n, f|
if n >= 1
f.call()
times.call(n-1, f)
end
}
times.call(3, proc { puts “hello world” } )
However, I cheated The proc isn’t really anonymous because I
assigned
it to ‘times’, and this was essential because I referred to the name
inside the function in order to call itself recursively.
But in fact it’s possible to write fully anonymous functions which are
recursive.
The following example is translated from "Structure and Interpretation
of Computer Programs" (Abelson, Sussman and Sussman), second edition
p393
- it’s an anonymous function which calculates factorial recursively
puts proc { |n|
proc { |fact| fact.call(fact, n) }.call(
proc { |ft, k|
k <= 1 ? 1 : k * ft.call(ft, k-1)
}
)
}.call(10)
Using this pattern we can recast our iterator as follows, without
using
its name internally:
proc { |*a|
proc { |iter| iter.call(iter, *a) }.call(
proc { |me, n, f|
if n >= 1
f.call()
me.call(me, n-1, f)
end
}
)
}.call(3, proc { puts “hello again” } )