views:

64

answers:

3

Given this code:

a = {1=>2}
m = a.method(:[])

I know that I can now use :

value = m.call(1)

and it will return 2. The thing is, what do I need to change so that I can call the method directly like :

m.call()

and it will get the 1 sent as a parameter? It would be nice to be able to write something like :

m = a.method(:[],1) # where the symbol is the method, and 1 will be the parameter it will be called with

The thing is, I'd like to delay the execution of certain parts of my script until some objects get created, and I'd like to avoid rewriting EVERYTHING to use lambdas.

+3  A: 

There's more than one way to do it, I'm sure.

a = {1=>2}

class << a
  def fetch_what(key)
    Proc.new { self[key] }
  end
end

....

m = a.fetch_what(1)
m.call()  # -> 2
pilcrow
This is pretty neat. I wonder if there are other ways.
Geo
A: 
sheldonh
I'd just like to lazy it up. This way, when it will get called, the values I'm looking for will exist.
Geo
Yes. That's what I'm suggesting.
sheldonh
+3  A: 

Basically, what you want is a way to curry the function.

http://en.wikipedia.org/wiki/Curry%5Ffunction

This can be done in many different ways, one of which:

def curry(method, *params)
  lambda { send method, *params }
end

You can add this to Hash's metaclass, or to a module you want to include in some of your objects, etc. Then, calling it becomes the usecase you wanted:

irb(main):001:0> a = {1 => 2}
=> {1=>2}
... # add curry to Hash's metaclass
irb(main):011:0> m = a.curry :[], 1
=> #<Proc:0xb76e2154@(irb):8>
irb(main):012:0> m.call
=> 2
Marcos Toledo
It would have been nice if this was already part of `Object`.
Geo