Difference between inject and reduce

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? 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.

···


Travis Whitton whitton@atlantic.net

I’d just change it to: car, cdr = array[0], array[1…-1] # for brevity
Of course, you could use partition, but that’s fairly heavy handed.

If I needed this often enough I’d add…
class Array
def car; first; end
def cdr; self[1…-1]; end
end
… for convenience.

Any other suggestions?

~ Bruce

···

On Monday 21 October 2002 03:34 pm, Travis Whitton wrote:

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.

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”