Skip to content

Instantly share code, notes, and snippets.

@benhamill
Created February 2, 2013 04:29
Show Gist options
  • Save benhamill/4696115 to your computer and use it in GitHub Desktop.
Save benhamill/4696115 to your computer and use it in GitHub Desktop.
How I Want Ruby's `Object#method` To Work

How I Want Ruby's Object#method To Work

The simple case, is this guy:

> m = SecureRandom.method(:hex)
=> #<Method: SecureRandom.hex>
> m.call
=> "5928aab178404945fb560a249b67a000"
> m.call
=> "d5ba69ac2e9dc8632aee7bf3212f6d67"

But, what I want, is a fully curried function. Something like this:

> m = SecureRandom.method(:hex, 6)
=> #<Method: SecureRandom.hex>
> m.call
=> "bd131d38de3c"
> m.call
=> "4e5a20936be0"

But Object#method doesn't take more than one argument. So, to get the effect I want, I have to do something like this:

> m = -> { SecureRandom.hex(6) }
=> #<Proc:0x000000034144b8@(pry):7 (lambda)>
> m.call
=> "bd131d38de3c"
> m.call
=> "4e5a20936be0"

It's not a huge thing, just a little sugar, but still.

@benhamill
Copy link
Author

So @avdi pointed out Proc#curry. And I tried it out, but it's a bit weird about arity:

> p = SecureRandom.method(:hex).to_proc
=> #<Proc:0x000000030b2590 (lambda)>
> p.airty
=> -1
> p1 = p.curry
=> #<Proc:0x0000000312f400 (lambda)>
> p1.arity
=> -1
> p1.call
=> "de22fd26a6f63516f9a1c32147cadc44"
> p1.call(5)
=> "1f5e2b31f6"
> p2 = p.curry[5]
=> "ed76826b41"
> # Oh. That's not a Proc...
> p2.call
NoMethodError: undefined method 'call' for "ed76826b41":String
> p3 = p.curry(1)[5]
=> "6c08b6f144"
> # That's not one, either...
> p4 = p.curry(2)[5]
=> #<Proc:0x000000031e4fd0 (lambda)>
> # OK. Closerrrrrr...
> p4.call
=> #<Proc:0x000000031f8cd8 (lambda)>
> # Uh... no.
> p4.call(0)
ArgumentError: wrong number of arguments (2 for 1)
from /home/ben/.rbenv/versions/1.9.3-p286/lib/ruby/1.9.1/securerandom.rb:139:in 'hex'
> # Shit.

Basically, as soon as the arity of the curried function is met, it evaluates it down, so you can't fill the args all up and then wait to call it... without explicitly making a lambda.

@jcsalterego
Copy link

Name my method Object#cmethod and call it a day :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment