Difference between inject and reduce 
Author Message
 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.

--



Sat, 09 Apr 2005 03:20:40 GMT  
 Difference between inject and reduce

Quote:
> 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.

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



Sat, 09 Apr 2005 05:27:19 GMT  
 Difference between inject and reduce
Am 2002-10-22 04:34:32 +0900 schrieb Travis Whitton:

Quote:
> 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 }

(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*

Quote:
> 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.

--
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"



Sat, 09 Apr 2005 10:02:30 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. Yacc/Bison: reduce/reduce-conflict

2. To Reduce or Not To Reduce

3. Terse blocks (was: Re: Shorthanding inject:into:)

4. inject:into:

5. Shorthanding inject:into:

6. Thots on #inject:into:

7. Information on Injecting errors in ASIC verification.

8. Injecting faults within the PLI environment

9. Injecting a value onto the stack

10. Injecting methods from one object to another

11. Regarding inject:into:

12. inject:into:

 

 
Powered by phpBB® Forum Software