From: Brian Candler Date: 2007-03-01T07:20:28+09:00 Subject: Functional programming in Ruby 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" } )