Passing method references in python & ruby

Hey all,

Kind of an idle, syntax comparison question here...

In python, you can apparently pass method references around very
easily. So imagine you have these 2 functions defined:

   def firstWay(arg1, arg2)
      return 'Tastes great.'

   def secondWay(arg1, arg2)
      return 'Less filling.'

Then you can define a method that takes a method name as an argument,
and calls it just by throwing parens (and any expected arguments of
course) after it.

   def doStuff(whichway, first_arg, second_arg)
      return whichway(first_arg, second_arg)

So calling:

   puts doStuff(firstWay, None, None)

Would result in 'Tastes great.'

What's the most graceful way to do this sort of thing in ruby? I
tried passing in e.g., firstWay.to_proc, but that got me a complaint
about not having enough arguments on the call. I can imagine doing,
e.g.,

   first_pointer = Proc.new do |foo, bar|
      return firstWay(foo, bar)
   end

One for each alternate method & passing one of those in. I can also
imagine having doStuff take a block that would call the desired
function & yielding out to that. But neither of those are as pretty
as the python I think. Are those my best options in ruby, or is there
another way?

Thanks!

-Roy

rpardee@gmail.com wrote:

Hey all,

Kind of an idle, syntax comparison question here...

In python, you can apparently pass method references around very
easily. So imagine you have these 2 functions defined:

   def firstWay(arg1, arg2)
      return 'Tastes great.'

   def secondWay(arg1, arg2)
      return 'Less filling.'

Then you can define a method that takes a method name as an argument,
and calls it just by throwing parens (and any expected arguments of
course) after it.

   def doStuff(whichway, first_arg, second_arg)
      return whichway(first_arg, second_arg)

So calling:

   puts doStuff(firstWay, None, None)

Would result in 'Tastes great.'

What's the most graceful way to do this sort of thing in ruby? I
tried passing in e.g., firstWay.to_proc, but that got me a complaint
about not having enough arguments on the call. I can imagine doing,
e.g.,

   first_pointer = Proc.new do |foo, bar|
      return firstWay(foo, bar)
   end

One for each alternate method & passing one of those in. I can also
imagine having doStuff take a block that would call the desired
function & yielding out to that. But neither of those are as pretty
as the python I think. Are those my best options in ruby, or is there
another way?

Thanks!

-Roy

Here is another way:

irb(main):001:0> def dostuff(whichway, arg1, arg2)
irb(main):002:1> send(whichway, arg1, arg2)
irb(main):003:1> end
=> nil
irb(main):004:0> def first_way(arg1, arg2)
irb(main):005:1> "tastes great"
irb(main):006:1> end
=> nil
irb(main):007:0> def second_way(arg1, arg2)
irb(main):008:1> "less filling"
irb(main):009:1> end
=> nil
irb(main):010:0> dostuff(:first_way, nil, nil)
=> "tastes great"
irb(main):011:0> dostuff(:second_way, nil, nil)
=> "less filling"
irb(main):012:0> "No! #{dostuff(:first_way, nil, nil).capitalize}!"
=> "No! Tastes great!"

-Justin

> Hey all,
>
> Kind of an idle, syntax comparison question here...
>
> In python, you can apparently pass method references around very
> easily. So imagine you have these 2 functions defined:
>
> def firstWay(arg1, arg2)
> return 'Tastes great.'
>
> def secondWay(arg1, arg2)
> return 'Less filling.'
>
> Then you can define a method that takes a method name as an argument,
> and calls it just by throwing parens (and any expected arguments of
> course) after it.
>
> def doStuff(whichway, first_arg, second_arg)
> return whichway(first_arg, second_arg)
>
> So calling:
>
> puts doStuff(firstWay, None, None)
>
> Would result in 'Tastes great.'
>
> What's the most graceful way to do this sort of thing in ruby? I
> tried passing in e.g., firstWay.to_proc, but that got me a complaint
> about not having enough arguments on the call. I can imagine doing,
> e.g.,
>
> first_pointer = Proc.new do |foo, bar|
> return firstWay(foo, bar)
> end
>
> One for each alternate method & passing one of those in. I can also
> imagine having doStuff take a block that would call the desired
> function & yielding out to that. But neither of those are as pretty
> as the python I think. Are those my best options in ruby, or is there
> another way?
>
> Thanks!
>
> -Roy
>
>

Here is another way:

irb(main):001:0> def dostuff(whichway, arg1, arg2)
irb(main):002:1> send(whichway, arg1, arg2)
irb(main):003:1> end
=> nil

#dostuff is really superfluous because the way you defined it it's
just an alias for #send.

irb(main):004:0> def first_way(arg1, arg2)
irb(main):005:1> "tastes great"
irb(main):006:1> end
=> nil
irb(main):007:0> def second_way(arg1, arg2)
irb(main):008:1> "less filling"
irb(main):009:1> end
=> nil
irb(main):010:0> dostuff(:first_way, nil, nil)
=> "tastes great"
irb(main):011:0> dostuff(:second_way, nil, nil)
=> "less filling"
irb(main):012:0> "No! #{dostuff(:first_way, nil, nil).capitalize}!"
=> "No! Tastes great!"

So basically you would just do

send(:first_way, nil, nil)
send(:second_way, nil, nil)

However, if there are /many/ alternatives, then - depending on
circumstances - a Hash might be a better alternative:

algorithms = {
  :first_way => lambda {|a,b| 'Tastes great.'},
  :second_way => lambda {|a,b| 'Less filling'},
  # more algorithms here...
}
# ...
puts algorithms[:first_way][nil, nil]
puts algorithms[:second_way][nil, nil]

Kind regards

robert

···

2008/1/18, Justin Collins <justincollins@ucla.edu>:

rpardee@gmail.com wrote:

--
use.inject do |as, often| as.you_can - without end

Ah--that is nicer--thanks!

My momentary python envy (hmmm...) has now passed. :wink:

-Roy

···

On Jan 17, 8:12 pm, Justin Collins <justincoll...@ucla.edu> wrote:

rpar...@gmail.com wrote:
> Hey all,

> Kind of an idle, syntax comparison question here...

> In python, you can apparently pass method references around very
> easily. So imagine you have these 2 functions defined:

> def firstWay(arg1, arg2)
> return 'Tastes great.'

> def secondWay(arg1, arg2)
> return 'Less filling.'

> Then you can define a method that takes a method name as an argument,
> and calls it just by throwing parens (and any expected arguments of
> course) after it.

> def doStuff(whichway, first_arg, second_arg)
> return whichway(first_arg, second_arg)

> So calling:

> puts doStuff(firstWay, None, None)

> Would result in 'Tastes great.'

> What's the most graceful way to do this sort of thing in ruby? I
> tried passing in e.g., firstWay.to_proc, but that got me a complaint
> about not having enough arguments on the call. I can imagine doing,
> e.g.,

> first_pointer = Proc.new do |foo, bar|
> return firstWay(foo, bar)
> end

> One for each alternate method & passing one of those in. I can also
> imagine having doStuff take a block that would call the desired
> function & yielding out to that. But neither of those are as pretty
> as the python I think. Are those my best options in ruby, or is there
> another way?

> Thanks!

> -Roy

Here is another way:

irb(main):001:0> def dostuff(whichway, arg1, arg2)
irb(main):002:1> send(whichway, arg1, arg2)
irb(main):003:1> end
=> nil
irb(main):004:0> def first_way(arg1, arg2)
irb(main):005:1> "tastes great"
irb(main):006:1> end
=> nil
irb(main):007:0> def second_way(arg1, arg2)
irb(main):008:1> "less filling"
irb(main):009:1> end
=> nil
irb(main):010:0> dostuff(:first_way, nil, nil)
=> "tastes great"
irb(main):011:0> dostuff(:second_way, nil, nil)
=> "less filling"
irb(main):012:0> "No! #{dostuff(:first_way, nil, nil).capitalize}!"
=> "No! Tastes great!"

-Justin

In python when you use method name without parenthesises you get
method reference. In Ruby it won't work beacuse method can be called
without parenthesises (and Ruby programmers love it :)). If you want
to get method reference you can use method(:you_method_name) and you
get reference to Method instance. Later you can just call 'call'
method and pass some parameters. Direct traslation of your program to
Ruby looks like:

def firstWay(arg1, arg2)
  return 'Tastes great.'
end

def secondWay(arg1, arg2)
  return 'Less filling.'
end

def doStuff(whichway, first_arg, second_arg)
  return whichway.call(first_arg, second_arg)
end

puts doStuff(method(:firstWay), nil, nil)

···

--
Radosław Bułat

http://radarek.jogger.pl - mój blog

Well that is good, but for the wrong reason :frowning:

Our Rubyists where cheating on you as you had a first class object
called a function, and we were just using names.
Now there are no functions in Ruby so we cannot pass them on, we do
however have proc objects which would mimick what you have done in
Python
firstway =lambda{ |x| x+1}
otherway = lambda{ |x| x - 1}
def anyway away, anumber
    away.call anumber
end

However the interesting and somewhat frustrating stuff starts with
methods which are first class objects in Ruby
class A
    def first x; x+1 end
    def second x; x-1 end
    @f = instance_method :first
    @s = instance_method :second
    class << self
       attr_reader :f, :s
    end

    def any method, number
        method.bind( self ).call number
    end
end

p A.new.any(A.f, 41)
p A.new.any(A.s,43)

Things are however a little bit trickier when it comes to binding
instance_methods
look at this code
class B
   def b; 42 end
end

p B.instance_method(:b).bind(Object.new).call # :(((
I still fail to see the need for this restriction
Now lots of trickery is needed if you want to do things like these

module M
  def m; 42 end
end

p Object.new.send(:extend, M).m

If you are interested in this stuff you might have a look at the
implementation of Traits in Ruby
http://rubyforge.org/projects/ruby-traits/
HTH
Robert

···

On Jan 18, 2008 6:50 PM, rpardee@gmail.com <rpardee@gmail.com> wrote:

My momentary python envy (hmmm...) has now passed. :wink:

--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

Radosław Bułat wrote:

In python when you use method name without parenthesises you get
method reference. In Ruby it won't work beacuse method can be called
without parenthesises (and Ruby programmers love it :)). If you want
to get method reference you can use method(:you_method_name) and you
get reference to Method instance. Later you can just call 'call'
method and pass some parameters. Direct traslation of your program to
Ruby looks like:

def firstWay(arg1, arg2)
  return 'Tastes great.'
end

def secondWay(arg1, arg2)
  return 'Less filling.'
end

def doStuff(whichway, first_arg, second_arg)
  return whichway.call(first_arg, second_arg)
end

puts doStuff(method(:firstWay), nil, nil

Ah, that's the one I was looking for. Then you can do:

def doStuff(whichway, first_arg, second_arg)
  whichway[first_arg, second_arg]
end

-Justin

I still fail to see the need for this restriction

Without this restriction you can write

   Array.instance_method(:).bind(Hash.new).call(0)

and if you are not lucky ruby just crash.

Guy Decoux

Yeah, but do you really consider

doStuff(method(:firstWay), nil, nil)

more concise than

send(:firstWay, nil, nil)

?

Cheers

  robert

···

On 18.01.2008 20:11, Justin Collins wrote:

Radosław Bułat wrote:

In python when you use method name without parenthesises you get
method reference. In Ruby it won't work beacuse method can be called
without parenthesises (and Ruby programmers love it :)). If you want
to get method reference you can use method(:you_method_name) and you
get reference to Method instance. Later you can just call 'call'
method and pass some parameters. Direct traslation of your program to
Ruby looks like:

def firstWay(arg1, arg2)
  return 'Tastes great.'
end

def secondWay(arg1, arg2)
  return 'Less filling.'
end

def doStuff(whichway, first_arg, second_arg)
  return whichway.call(first_arg, second_arg)
end

puts doStuff(method(:firstWay), nil, nil

Ah, that's the one I was looking for. Then you can do:

def doStuff(whichway, first_arg, second_arg)
  whichway[first_arg, second_arg]
end

> I still fail to see the need for this restriction

Without this restriction you can write

   Array.instance_method(:).bind(Hash.new).call(0)

and if you are not lucky ruby just crash.

Bad example of mine, what disturbs me is the following

not working:
Module::new{ def a; 42 end}.instance_method(:a).bind(Object.new).call

not working:
a=Modul::new{ def a; 42 end}.i_m :a
Object.module_eval{ define_method :x, a }

working;
module M
  def m; 42 end
end

Object.module_eval{
    include M
    define_method :x, M.instance_method(:m)
}
p Object.new.x

and I thought we were all ducktypers :frowning:

Robert

···

On Jan 19, 2008 1:59 PM, ts <decoux@moulon.inra.fr> wrote:

Guy Decoux

--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

Robert Klemme wrote:

···

On 18.01.2008 20:11, Justin Collins wrote:

Radosław Bułat wrote:

In python when you use method name without parenthesises you get
method reference. In Ruby it won't work beacuse method can be called
without parenthesises (and Ruby programmers love it :)). If you want
to get method reference you can use method(:you_method_name) and you
get reference to Method instance. Later you can just call 'call'
method and pass some parameters. Direct traslation of your program to
Ruby looks like:

def firstWay(arg1, arg2)
  return 'Tastes great.'
end

def secondWay(arg1, arg2)
  return 'Less filling.'
end

def doStuff(whichway, first_arg, second_arg)
  return whichway.call(first_arg, second_arg)
end

puts doStuff(method(:firstWay), nil, nil

Ah, that's the one I was looking for. Then you can do:

def doStuff(whichway, first_arg, second_arg)
  whichway[first_arg, second_arg]
end

Yeah, but do you really consider

doStuff(method(:firstWay), nil, nil)

more concise than

send(:firstWay, nil, nil)

?

Cheers

    robert

Clearly this is just a toy example to show options for how one might call methods using variable names. If the doStuff method actually did more stuff, then it would no longer be equivalent to send.

-Justin

What bugs me about ruby is that I can't do this
def add_one(n)
  n + 1
end
[3,6,8].map(add_one)
=> [4,7,9]

I can't even do it more explicitly, because map won't take anything
other than a block:

irb(main):001:0> class A; def A.addone(x); x + 1; end; end
=> nil
irb(main):002:0> A.method(:addone)
=> #<Method: A.addone>
irb(main):003:0> [3,6,8].map{|x| x + 1}
=> [4, 7, 9]
irb(main):004:0> [3,6,8].map(A.method(:addone))
ArgumentError: wrong number of arguments (1 for 0)
        from (irb):4:in `map'
        from (irb):4
irb(main):005:0> [3,6,8].map(Proc.new{|x| A.method(:addone).call(x)})
ArgumentError: wrong number of arguments (1 for 0)
        from (irb):5:in `map'
        from (irb):5
irb(main):006:0> [3,6,8].map Proc.new{|x| A.method(:addone).call(x)}
ArgumentError: wrong number of arguments (1 for 0)
        from (irb):6:in `map'
        from (irb):6

Any of these would be defeating the purpose of brevity anyway. The best
I can do is to make a block that calls the proc I want:

irb(main):007:0> [3,6,8].map{|x| A.method(:addone).call(x)}
=> [4, 7, 9]

or more simply:
irb(main):008:0> [3,6,8].map{|x| A.addone(x)}
=> [4, 7, 9]

this seems a waste of keystrokes, a cognitive indirection, and probably
even a few processor cycles. Is there a way?

Grem

···

--
Posted via http://www.ruby-forum.com/.

Hi there,

You can skip the between and do this:

def add_one(n)
n+1
end

=> nil

[3,6,8].map &method(:add_one)

=> [4, 7, 9]

Personally, I like doing it this way. You could always try monkey-patching
(ooh, buzzword) Symbol by adding Symbol#to_proc to do some method
resolution. Not sure how well it'll work for you, but a guess.

Arlen

Gregory Marton wrote:

What bugs me about ruby is that I can't do this
def add_one(n)
n + 1
end
[3,6,8].map(add_one)
=> [4,7,9]

[3,6,8].map(&method(:add_one))
#=> [4, 7, 9]

And yeah, it'd be nice if there was a more concise syntax than that, but
that's what we've currently got. Thinking about it, you could do something
like this if you want a shorter syntax:

class Symbol
  def -@()
    method(self)
  end
end
[3,6,8].map(&-:add_one)

But that's kinda hackish.

HTH,
Sebastian

···

--
Jabber: sepp2k@jabber.org
ICQ: 205544826

Sorry, I missed your exact example. It works the same:

class A; def A.add_one(n); n + 1; end; end

=> nil

[3, 6, 8].map &A.method(:add_one)

=> [4, 7, 9]

Cheers,
Arlen.

Oh you might do this even very often if you are writing Ruby1.8/1.9
agnostic libraries.
Cheers
Robert

···

On Sun, Feb 24, 2008 at 2:55 PM, Arlen Cuss <celtic@sairyx.org> wrote:

Hi there,

You can skip the between and do this:

>> def add_one(n)
>> n+1
>> end
=> nil
>> [3,6,8].map &method(:add_one)
=> [4, 7, 9]

Personally, I like doing it this way. You could always try monkey-patching
(ooh, buzzword) Symbol by adding Symbol#to_proc to do some method
resolution.

--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

Not necessary. Here's another approach that has the added advantage that it will also work with 1.8 - and it's short and conscise:

irb(main):001:0> add_one = lambda {|x| x + 1}
=> #<Proc:0x7ff9c4bc@(irb):1>
irb(main):002:0> (1..3).map &add_one
=> [2, 3, 4]
irb(main):003:0>

Although I have to say it's not clear to me what speaks against doing
(1..3).map {|x| x + 1}.

Kind regards

  robert

···

On 24.02.2008 14:55, Arlen Cuss wrote:

You can skip the between and do this:

def add_one(n)
n+1
end

=> nil

[3,6,8].map &method(:add_one)

=> [4, 7, 9]

Personally, I like doing it this way. You could always try monkey-patching
(ooh, buzzword) Symbol by adding Symbol#to_proc to do some method
resolution. Not sure how well it'll work for you, but a guess.

Robert Dober wrote:

···

On Sun, Feb 24, 2008 at 2:55 PM, Arlen Cuss <celtic@sairyx.org> wrote:

=> [4, 7, 9]

Personally, I like doing it this way. You could always try monkey-patching
(ooh, buzzword) Symbol by adding Symbol#to_proc to do some method
resolution.

Oh you might do this even very often if you are writing Ruby1.8/1.9
agnostic libraries.
Cheers
Robert

Could you both elaborate? I'm not sure what it would mean to
"monkeypatch" this, or which differences with 1.9 will require it.
Thanks already: this is a bit C-like, but nicer than wrapping a block
around things.

Grem
--
Posted via http://www.ruby-forum.com/\.

Another potentially easy question:

I'd like to pass a surround method into another, where the surround
method would take a block, and should yield to it, perhaps doing stuff
before and after. This is not a real call/cc surround, just something
simple. So:

def do_things(options={})
  opts = {:surround => Proc.new{yield}}.merge(options)
  opts[:surround] do
    the actual task
  end
end

except this doesn't actually work with Procs, because opts[:surround] is
an undefined method, of course. It contains a method reference. Well,
rather, a procedure reference. In any case, I want to invoke it with a
block.

so I think
  y = lambda{ yield }
  y.call{ 3 }
perhaps, but no:
LocalJumpError: no block given

How shall I pass it a block?

Thanks,
Grem

···

--
Posted via http://www.ruby-forum.com/.

Robert Dober wrote:

>> => [4, 7, 9]
>>
>> Personally, I like doing it this way. You could always try monkey-patching
>> (ooh, buzzword) Symbol by adding Symbol#to_proc to do some method
>> resolution.
> Oh you might do this even very often if you are writing Ruby1.8/1.9
> agnostic libraries.
> Cheers
> Robert

Could you both elaborate? I'm not sure what it would mean to
"monkeypatch" this, or which differences with 1.9 will require it.
Thanks already: this is a bit C-like, but nicer than wrapping a block
around things.

Symbol#to_proc exists in Ruby1.9 standard, if you want to have
programs run in Ruby1.8 too you will be forced to define your
Symbol#to_proc yourself.
But I guess that I am wrong that you have to do that often, that was
written with very little thinking done :(.

Robert

···

On Sun, Feb 24, 2008 at 3:05 PM, Gregory Marton <q8pb97u001@sneakemail.com> wrote:

> On Sun, Feb 24, 2008 at 2:55 PM, Arlen Cuss <celtic@sairyx.org> wrote:

Grem
--
Posted via http://www.ruby-forum.com/\.

--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein