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}

# and this is the same as:

array.each_with_object({}) { |x, h| h = 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}
array.each_with_object({}) { |x, h| h = 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 Programming Language" book (O'Reilly).

Abinoam Jr.

···

On Fri, Sep 27, 2013 at 4:31 PM, Martin DeMello <martindemello@gmail.com> wrote:

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

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| i*2 } * 3
  => 3
  irb(main):002:0> 1.tap{|i| break i*2 } * 3
  => 6

···

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

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

Why not tap! ?

Abinoam Jr.

···

On Sat, Sep 28, 2013 at 9:30 AM, Matthew Kerwin <lists@ruby-forum.com> wrote:

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

Feature #6721: Object#yield_self - Ruby master - Ruby Issue Tracking System (exactly this feature, in a
round-about way)

Feature #6373: public #self - Ruby master - Ruby Issue Tracking System (slightly related)

You can also do this trick using #tap:

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

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

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

···

On Sun, Sep 29, 2013 at 4:06 AM, Abinoam Jr. <abinoam@gmail.com> wrote:

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

Why not tap! ?

Abinoam Jr.

On Sat, Sep 28, 2013 at 9:30 AM, Matthew Kerwin <lists@ruby-forum.com> wrote:

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)

Feature #6373: public #self - Ruby master - Ruby Issue Tracking System (slightly related)

You can also do this trick using #tap:

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

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