Project

General

Profile

Feature #6717

Method like #instance_eval that returns self (like #tap)

Added by alexeymuranov (Alexey Muranov) almost 7 years ago. Updated almost 7 years ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:46296]

Description

=begin
How about adding a method that acts like (({#instance_eval})), but returns (({self}))?

Call it (({Object#instance_tap})) for example, or (({Object#tweak!})):

class Object
def tweak!(*args, &block)
instance_eval(*args, &block); self
end
end

This can be used to initialize a hash. Instead of:

room_numbers = (1..10).each_with_object({}) { |n, o| o[n] = 100 + n }

one would write:

room_numbers = {}.tweak! { (1..10).each { |n| self[n] = 100 +n } }

Googling for this kind of method gave me this:
http://yuroyoro-blog.tumblr.com/post/24113917395/ruby-tap-instance-eval-tapeval
=end

History

Updated by alexeymuranov (Alexey Muranov) almost 7 years ago

=begin
For a few hours already i like this method so much, that i want to propose a short name for it: (({Object#!})) :) :

room_numbers = {}.! { (1..10).each { |n| self[n] = 100 + n } }

=end

Updated by nobu (Nobuyoshi Nakada) almost 7 years ago

=begin
I'm against adding new methods which call (({instance_eval})) under the hood.
=end

Updated by alexeymuranov (Alexey Muranov) almost 7 years ago

=begin
It seems to me that the main question is if to allow new methods that act like (({instance_eval})), or call it under the hood. The advantage in my opinion is the possibility to use (({self})), instead of choosing and declaring a local variable like in:

room_numbers = {}.tap { |h| (1..10).each { |n| h[n] = 100 + n } }

and that the object itself can be modified. ((({tap})) will modify in place.)
=end

Updated by rosenfeld (Rodrigo Rosenfeld Rosas) almost 7 years ago

on the other hand that approach won't be suitable for nested tweak calls :)

Updated by alexeymuranov (Alexey Muranov) almost 7 years ago

=begin
Another idea: how about "associating" this method with "public self" requested in #6373?

class Object
def self
self
end

def self!(&block)
instance_eval(&block)
self
end
end

room_numbers = {}.self! { (1..10).each { |n| store(n, 100 + n) } }

Other possible names: (({Object#_})) and (({Object#!}))
=end

Updated by alexeymuranov (Alexey Muranov) almost 7 years ago

=begin
I think i've understood the concern of ((nobu)): object's private methods will be accessible from the block. This is not what i wanted. Sorry, i'll need to think more about my proposal. Maybe it is not good and (({tap})) is enough.

Here is why i am thinking about this: i want to be able to alter an object by calling methods on it, instead of passing the object as an argument (like in (({each_with_object}))).
=end

Updated by alexeymuranov (Alexey Muranov) almost 7 years ago

=begin
If nobody has anything interesting to say about this, the issue can be closed, as i think (({tap})) works fine here, even in:

hash = {}.tap { |h| h.tap { |hh| hh[1] = 2 } } # => {1=>2}

"Tap" just sounded strange to me in this use case. I wanted something like (({instance_eval})) that (1) returns self and (2) can only call public methods.

((rosenfeld)), what did you mean by "won't be suitable for nested tweak calls"?
=end

Updated by marcandre (Marc-Andre Lafortune) almost 7 years ago

  • Status changed from Open to Rejected

Updated by rosenfeld (Rodrigo Rosenfeld Rosas) almost 7 years ago

alexeymuranov (Alexey Muranov) wrote:

((rosenfeld)), what did you mean by "won't be suitable for nested tweak calls"?

=begin
{}.self! { {}.self! { store(...) } }
=end

Which store is used?

Also available in: Atom PDF