Object.method(f) = f.call(object)

Came across a need for this in a somewhat silly golfing exercise, but
I was wondering if there was any real use for it, and if it had a name
in some language somewhere. It essentially lets a block of code be
inserted into a method chain (a la Object#tap) but returns the return
value of the block rather than the passed in argument.

for example (using “apply” for want of a better name)

array.inject({}).map {|h, e| h[e] = f(e); h}

would become

array.map {|e| e, f(e)}.flatten.apply {|x| Hash[*x]}

martin

I think “apply” is a good name for that!

About your example.

array = (1…10).to_a

def f(x)
2*x
end

Would it be something like this?

class Object
def apply
yield self
end
end

array.inject({}) {|h, e| h[e] = f(e); h}

=> {1=>2, 2=>4, 3=>6, 4=>8, 5=>10, 6=>12, 7=>14, 8=>16, 9=>18, 10=>20}

Bellow would be an option because merge! returns the hash.

array.inject({}) {|h, e| h.merge!(e=>f(e)) }

and

array.map {|e| [e, f(e)]}.flatten.apply {|x| Hash[*x]}

=> {1=>2, 2=>4, 3=>6, 4=>8, 5=>10, 6=>12, 7=>14, 8=>16, 9=>18, 10=>20}

I think you can split ou the “flatten” and the “splat” together.

array.map {|e| [e, f(e)]}.apply {|x| Hash[x]}

and this is the same as:

array.each_with_object({}) { |x, h| h[x] = f(x) }

=> {1=>2, 2=>4, 3=>6, 4=>8, 5=>10, 6=>12, 7=>14, 8=>16, 9=>18, 10=>20}

puting them side-by-side

array.map {|e| [e, f(e)]}.apply {|x| Hash[x]}
array.each_with_object({}) { |x, h| h[x] = f(x) }

IMHO I think the second is clearer!

Perhaps the “apply” is not usually needed because …

pairs = array.map {|e| [e, f(e)]}
hash = Hash[pairs]}

And… what a coincidence!

https://groups.google.com/d/msg/rubyonrails-talk/1TfRGnnFfwc/J8J59sEyaCQJ

The guy over there is also using this Hash[*something] to generate the
Hash. (Talked to him these days)

Found this also…
https://code.google.com/p/tokland/wiki/RubyFunctionalProgramming#How_to_create_a_hash_from_an_enumerable

And about “apply”, I think I saw something on chapter about Functional
Programming on “The Ruby P.ming Language” book (O’Reilly).

Abinoam Jr.

For the record, you should have a read of these feature requests:

http://bugs.ruby-lang.org/issues/6721 (exactly this feature, in a
round-about way)

http://bugs.ruby-lang.org/issues/6373 (slightly related)

You can also do this trick using #tap:

irb(main):001:0> 1.tap{|i| i2 } * 3
=> 3
irb(main):002:0> 1.tap{|i| break i
2 } * 3
=> 6

Having thought about it I still like ‘apply’. It doesnt have the
connotation that the object itself is being changed (unlike, e.g.
‘morph’ from that discussion), and it’s fairly close to the lisp
meaning of (apply f x) => (f x)

martin

Thanks Mathew for pointing them.
I’ve just made a name suggestion over there.

Why not tap! ?

Abinoam Jr.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs