Peter
Peter

Reputation: 132247

Method pointers in ruby

I want to store several different methods in an array in Ruby. Suppose I want to store the type method twice:

[type, type]

doesn't store two entries of type in an array; it executes type twice, and stores the results in the array. how do I refer explicitly to the method object itself?

(this is just a simplified version of what I really want.)

EDIT: on second thoughts, it bothers me that the solution proposed below avoids the problem by passing the name of the method. how do you pass the method object itself? for example, what if you pass [:type, :type] to a method that has an alternative resolution for type? how can you pass the type method object itself?

Upvotes: 18

Views: 16579

Answers (3)

August Lilleaas
August Lilleaas

Reputation: 54593

If you're thinking about doing method references in Ruby, you're doing it wrong.

There is a built-in method in Ruby called method. It will return a proc version of the method. It is not a reference to the original method, though; every call to method will create a new proc. Changing the method won't affect the proc, for example.

def my_method
  puts "foo"
end

copy = method(:my_method)

# Redefining
def my_method
  puts "bar"
end

copy.call
# => foo

When you want to store pieces of code, and don't want to use regular methods, use procs.

stack = [proc { do_this }, proc { do_that }]
stack.each {|s| s.call }

Upvotes: 13

Chuck
Chuck

Reputation: 237060

If you want to store a method rather than the result of calling a method or just the message you'd send to invoke it, you need to use the method method on the owning object. So for example

"hello".method(:+)

will return the + method of the object "hello", so that if you call it with the argument " world", you'll get "hello world".

helloplus = "hello".method(:+)
helloplus.call " world" # => "hello world"

Upvotes: 39

Josh Matthews
Josh Matthews

Reputation: 13026

[:type, :type].collect { |method_name| self.send(method_name) }

Alternatively, if the method is part of an object:

method = obj.method(:type)
values = [method.call, method.call]

Upvotes: 1

Related Questions