Forum: Ruby How to pass a function as argument in ruby?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
5d08037b126716e96ddabb1a12d783a0?d=identicon&s=25 the_crazy88 (Guest)
on 2006-02-12 22:23
(Received via mailing list)
I've searched a bit about the subject, but I don't understand it. All I
want is to simply pass a function of one instance to another. In Python
this works, but in ruby not.

Python code would be:
def x(a,b):
  return a+b

def y(a):
  return a(3,4)

y(x)
# Result is 7
But the equivalent ruby code doesn't work:

def a(x,y)
  return x+y
end

def x(b)
  return b(3,4)
end

x(a)
 #Gives the following error in irb:

NoMethodError: undefined method `b' for main:Object
        from (irb):40:in `x'
        from (irb):42
        from :0
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-02-12 22:36
(Received via mailing list)
Hi --

On Mon, 13 Feb 2006, the_crazy88 wrote:

>
> y(x)
> # Result is 7
> But the equivalent ruby code doesn't work:

That's because it's not equivalent :-)

>
> NoMethodError: undefined method `b' for main:Object
>        from (irb):40:in `x'
>        from (irb):42
>        from :0

It shouldn't; it should complain that you've called a with no
arguments instead of two.

When you do this:

   x(a)

Ruby evaluates the expression 'a', and that's a method call -- so it
tries to call the method a, but that method takes two arguments and
you haven't provided any.

You can pass method names around, as strings or symbols, and then
"send" the method name to an object (or self, by default):

   def a(x,y)
     x + y
   end

   def x(b)
     send(b,3,4)
   end

   puts x(:a)  # 7

There are also some more elaborate mechanisms involving Method
objects, but the above might achieve what you need.


David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-02-12 22:38
(Received via mailing list)
On Feb 12, 2006, at 3:23 PM, the_crazy88 wrote:

> x(a)
>  #Gives the following error in irb:

You can ask for a method object and call it when needed:

def a(x,y)
   return x+y
end

def x(b)
   return b.call(3,4)
end

p x(method(:a))

Hope that helps.

James Edward Gray II
A9c4658e9e475e13d790ae419acf01b6?d=identicon&s=25 Simon Kröger (Guest)
on 2006-02-12 22:42
(Received via mailing list)
the_crazy88 wrote:
> I've searched a bit about the subject, but I don't understand it. All I
> want is to simply pass a function of one instance to another. In Python
> this works, but in ruby not.

def a(x,y)
   return x+y
end

def x(b)
   return b.call(3,4)
end

puts(x(method(:a)))

# or the ruby way:

def x
   yield 3, 4
end

puts(x{|a, b| a + b})

cheers

Simon
37a3c73ffbf864e4b28f7f2384ee12ce?d=identicon&s=25 Timothy Hunter (tim-hunter)
on 2006-02-12 22:48
(Received via mailing list)
the_crazy88 wrote:
>
> end
>
> x(a)
>  #Gives the following error in irb:
>
> NoMethodError: undefined method `b' for main:Object
>         from (irb):40:in `x'
>         from (irb):42
>         from :0
>

In Ruby it's typical to encapsulate bits of code in Proc objects and
pass these objects around:

p = Proc.new {|x,y} x+y}

p.call(2,3) -> 5

If you're really wanting to pass methods around from one instance to
another, check out the doc for the UnboundMethod class with ri.
430ea1cba106cc65b7687d66e9df4f06?d=identicon&s=25 David Vallner (Guest)
on 2006-02-12 22:52
(Received via mailing list)
DÅ?a Nedeľa 12 Február 2006 22:48 Timothy Hunter napísal:
> another, check out the doc for the UnboundMethod class with ri.
Or use Procs and inject the instance into them as a parameter, which is
a bit
more readable to me.

David Vallner
5d08037b126716e96ddabb1a12d783a0?d=identicon&s=25 the_crazy88 (Guest)
on 2006-02-13 09:58
(Received via mailing list)
Ok, thanks a lot everyone! Seems like a lot of usefull ideas.
5d08037b126716e96ddabb1a12d783a0?d=identicon&s=25 the_crazy88 (Guest)
on 2006-02-14 07:03
(Received via mailing list)
Though I tried your suggestions, something worked out much better. I
just needed to pass a reference to the calling class with the argument
self. That way I can call back functions just by executing them. For
example:

class Example
  attr_reader :show_info
  def initialize
     @instance = self
     @example2 = Example2.new(@instance)
  end
  def show_info(text)
    puts text
  end
end

class Example2
  def initialize(instance)
    @instance = instance
    @instance.show_info("Yes, this worked out :D")
  end
end
430ea1cba106cc65b7687d66e9df4f06?d=identicon&s=25 David Vallner (Guest)
on 2006-02-14 22:05
(Received via mailing list)
DÅ?a Utorok 14 Február 2006 07:03 the_crazy88 napísal:
> Though I tried your suggestions, something worked out much better. I
> just needed to pass a reference to the calling class with the argument
> self. That way I can call back functions just by executing them. For
> example:
>

There you go, proper OO instead of functional for the heck of it.

> class Example
>   attr_reader :show_info
The above line of code is completely unnecessary.
>   (snip)


David Vallner
This topic is locked and can not be replied to.