How to pass a function as argument in ruby?

Discussion in 'Ruby' started by the_crazy88, Feb 12, 2006.

  1. the_crazy88

    the_crazy88 Guest

    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
    the_crazy88, Feb 12, 2006
    #1
    1. Advertising

  2. the_crazy88

    Guest

    Hi --

    On Mon, 13 Feb 2006, 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.
    >
    > 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:


    That's because it's not equivalent :)

    > 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


    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 ()
    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
    , Feb 12, 2006
    #2
    1. Advertising

  3. On Feb 12, 2006, at 3:23 PM, the_crazy88 wrote:

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


    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
    James Edward Gray II, Feb 12, 2006
    #3
  4. 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
    Simon Kröger, Feb 12, 2006
    #4
  5. D=C5=88a Nede=C4=BEa 12 Febru=C3=A1r 2006 22:48 Timothy Hunter nap=C3=ADsal:
    > the_crazy88 wrote:
    >
    > In Ruby it's typical to encapsulate bits of code in Proc objects and
    > pass these objects around:
    >
    > p =3D 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.


    Or use Procs and inject the instance into them as a parameter, which is a b=
    it=20
    more readable to me.

    David Vallner
    David Vallner, Feb 12, 2006
    #5
  6. the_crazy88

    the_crazy88 Guest

    Ok, thanks a lot everyone! Seems like a lot of usefull ideas.
    the_crazy88, Feb 13, 2006
    #6
  7. the_crazy88

    the_crazy88 Guest

    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
    the_crazy88, Feb 14, 2006
    #7
  8. D=C5=88a Utorok 14 Febru=C3=A1r 2006 07:03 the_crazy88 nap=C3=ADsal:
    > 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
    David Vallner, Feb 14, 2006
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ben Kial
    Replies:
    1
    Views:
    616
    Eric Enright
    Nov 15, 2004
  2. S?ren Gammelmark
    Replies:
    1
    Views:
    1,856
    Eric Sosman
    Jan 7, 2005
  3. Reckoner
    Replies:
    11
    Views:
    674
    Steven D'Aprano
    Jan 19, 2009
  4. AikidoGuy
    Replies:
    11
    Views:
    533
    Seebs
    Nov 21, 2011
  5. Replies:
    8
    Views:
    107
Loading...

Share This Page