Lately I’ve been trying to learn more about functional programming and
understand more about ruby’s functional features in the process. In
studying SML, I’ve come across a function called reduce, which seems
very similar to ruby’s inject method. I’ve defined reduce in ruby as
follows:
def reduce(f, b, list)
if (list.empty?)
b
else
f.call(list.first, reduce(f, b, list[1, list.length]))
end
end
Am I correct in assuming the only difference between reduce and the
inject method described in the pickaxe book is that reduce takes an
anonymous method as an argument rather than inserting a block via
yield?
You could also use a Proc object with inject:
m = lambda { |x,y| x - y }
==>#Proc:0x001677ac@:3(irb)
(1…10).inject(0, &m)
==>-55
There’s a more important difference with m, because reduce returns
another value:
reduce(m, 0, list(*(1…10)))
==>-5
inject and reduce return equal values if the function is commutative. If
it isn’t (like m), they differ. You can see why if you go through the
steps in a calculation for a small example. inject is more similiar to
accumulate:
def accumulate(fun, x, list)
if null?(list)
x
else
accumulate(fun, fun.call(x, car(list)), cdr(list))
end
end
But inject is implemented iterative in C, because recursion isn’t as
efficient in Ruby as in FP languages which grok tail recursion.
BTW: I’ve implemented some of the usual functions used in FP as a fun
project in Ruby:
http://www.ping.de/~flori/programs.shtml#functional
Archive:
http://www.ping.de/~flori/programs/ruby/functional/functional.tgz
Module in Pretty HTML:
http://www.ping.de/~flori/programs/ruby/functional/func.rb.html
During this project I found out that 1. this is valid Ruby code
(def accumulate (fun, x, list)
(if (null? list)
x
else
(accumulate fun, (fun.call x, (car list)), (cdr list))
end)
end)
and 2. that “:set syntax=lisp” in vim while programming Ruby is very
useful in some cases. g
Also, when using ruby in a functional style is there a better way to
get the traditional car and cdr of an Array than array.first, array[1,
array.length]? I understand that an array is not the same thing as a
“list”, but I’m just thinking convience here.
Perhaps like that:
first, *list = list
But it is only shorter not more efficient I think.
···
Am 2002-10-22 04:34:32 +0900 schrieb Travis Whitton:
–
Give me a man or a woman who has read a thousand books and you give me an
interesting companion. Give me a man or a woman who has read perhaps three and
you give me a dangerous enemy indeed.
– Anne Rice, “The witching hour”