# Higher Order Functions

Discussion in 'Ruby' started by Nickolay Kolev, Jul 31, 2005.

1. ### Nickolay KolevGuest

Hi guys,

I have recently started learning Ruby having some background in
Python and Prolog. Being a fan of functional programming I want to
port the goopy functions (http://goog-goopy.sourceforge.net/
goopy.functional.html) in Ruby despite most of them having
straightforward equivalents in Ruby already. Just as an exercise. I
also saw it as a good way to teach myself about modules. And
eventually about unit testing.

My plan is to put all the functions in a module called Functional and
call them like Functional.func_name(params).

in fruby.rb:

module Functional

def Functional.every(f, lst)
lst.collect { |element| f(element) }
end

end

in test.rb:

require 'fruby'

def times_two(x)
x * 2
end

p Functional.everytimes_two, [1,2,3])

And I get this:

undefined method `f' for Functional:Module (NoMethodError)

How do I pass the times_two function to the module method?

Many thanks in advance!

-- Nicky

Nickolay Kolev, Jul 31, 2005

2. ### Charles SteinmanGuest

Nickolay Kolev wrote:
> in fruby.rb:
>
> module Functional
>
> def Functional.every(f, lst)
> lst.collect { |element| f(element) }
> end
>
> end
>
> in test.rb:
>
> require 'fruby'
>
> def times_two(x)
> x * 2
> end
>
> p Functional.everytimes_two, [1,2,3])
>
>
> And I get this:
>
> undefined method `f' for Functional:Module (NoMethodError)
>
> How do I pass the times_two function to the module method?

p Functional.every(methodtimes_two), [1,2,3]

And in Functional, it would be lst.collect { |element| f.call(element)
}

Just the token ":times_two" specifies a symbol. This symbol could
represent anything -- a method, a constant, a variable, nothing at all
-- so you use #method to get the method from the current context with a
corresponding name.

As a side note, I assume you realize that this is exactly the sort of
thing blocks are for, right?

Charles Steinman, Jul 31, 2005

3. ### Dave BurtGuest

"Nickolay Kolev" <> wrote...
> ...
> module Functional
>
> def Functional.every(f, lst)
> lst.collect { |element| f(element) }
> end
>
> end
>
> in test.rb:
>
> require 'fruby'
>
> def times_two(x)
> x * 2
> end
>
> p Functional.everytimes_two, [1,2,3])
>
>
> And I get this:
>
> undefined method `f' for Functional:Module (NoMethodError)

The problem here is that f(element) means call the method self.f (which
doesn't exist, hence the error), whereas you want to call the "function"
represented by the parameter f.

You can do this a couple of ways. Charles suggested you pass f as a Method
to every:
> p Functional.every(methodtimes_two), [1,2,3]
> And in Functional, it would be lst.collect { |element| f.call(element)
> }

f.call will also work if f is a Proc, so you could also do:
Functional.every(proc{|x| x * 2}, [1, 2, 3])

You can pass a symbol, but I wouldn't recommend it - make the caller pass a
callable object (a Proc or Method).

Cheers,
Dave

Dave Burt, Jul 31, 2005
4. ### gabriele renziGuest

Nickolay Kolev ha scritto:
> Hi guys,
>
> I have recently started learning Ruby having some background in Python
> and Prolog. Being a fan of functional programming I want to port the
> goopy functions (http://goog-goopy.sourceforge.net/
> goopy.functional.html) in Ruby despite most of them having
> straightforward equivalents in Ruby already. Just as an exercise. I
> also saw it as a good way to teach myself about modules. And eventually
> about unit testing.

great plan even if I'm a bit disappointed that the library seem to be
(almost) a list handling library.

> My plan is to put all the functions in a module called Functional and
> call them like Functional.func_name(params).
>
> in fruby.rb:
>
> module Functional
>
> def Functional.every(f, lst)
> lst.collect { |element| f(element) }
> end
>
> end

Notice you could just do
module Functional
def every... end
def any other... end
extend self
end

so that you could call it via Functiona.f and yet retain the ability to
include the module (say, in Enumerable

I also second the suggetsion to generally use a block wehenever possible
(i.e. 99% of the time)

gabriele renzi, Jul 31, 2005
5. ### Dave BurtGuest

>> Functional.every(proc{|x| x * 2}, [1, 2, 3])
>
> IMO, you should pass a block.
>
> Then, you still can call it like that:
>
> Functional.every [1,2,3], &methodfoo)

And better yet (IMO) is Ruby's own
[1, 2, 3].collect &methodfoo)

In the spirit of the thing, I'd prefer these functions to be first-class
themselves. Perhaps the most obvious way to do this is:
module Functional
def every
proc do |f, lst|
lst.collect {|element| f[element] }
end
end
end

Which could be used like this:
f = Functional.every
g = proc {|x| x * 2 }
p f[g, [1, 2, 3]]

I'm not up with procs taking blocks; I think it can't be done. And if not,
that's a barrier to using blocks in higher-order functions. You can pass
them as parameters, of course, as in my example.

This is Lispy, though - use square-brackets instead of "call" and you'll
have more brackets than alphanums before you know it!

Cheers,
Dave

Dave Burt, Jul 31, 2005
6. ### Nickolay KolevGuest

Hi all,

I was off computers fo a week, sorry for the late thanks. Ideas are
greatly appreciated, I will try them out.

Thanks again.

Nicky

Nickolay Kolev, Aug 8, 2005