Feature #15419
openAllow Kernel#tap to be invoked with arguments like Kernel#send
Description
Tapping methods without any arguments already has nice shorthand via Symbol#to_proc
:
object.tap { |o| o.example }
# vs
object.tap(&:example)
Unfortunately once other arguments are involved we have to switch back to the longer form:
array.merge(other).tap { |a| a.delete(object) }
This patch introduces a convenient and familiar shorthand for these cases which behaves similar to Kernel#send
:
array.merge(other).tap(:delete, object)
Calling tap without any arguments or block still raises LocalJumpError
:
3.tap #=> LocalJumpError: no block given
This also makes the existing shorthand even shorter:
object.tap { |o| o.example }
# vs
object.tap(&:example)
# vs
object.tap(:example)
Pull request: https://github.com/ruby/ruby/pull/2050
Updated by shuber (Sean Huber) about 6 years ago
The ruby/spec on Ruby 2.3
check is failing in this PR - I'm not sure what the existing conventions are for adding specs for new features like this.
- Should the new tests be wrapped in
unless RUBY_VERSION <= "2.3"
conditions? - Or should the new tests be added somewhere other than
/spec
instead? - Or some other convention? Please advise!
Updated by Eregon (Benoit Daloze) about 6 years ago
shuber (Sean Huber) wrote:
The
ruby/spec on Ruby 2.3
check is failing in this PR - I'm not sure what the existing conventions are for adding specs for new features like this.
- Should the new tests be wrapped in
unless RUBY_VERSION <= "2.3"
conditions?- Or should the new tests be added somewhere other than
/spec
instead?- Or some other convention? Please advise!
Yes, in such a case you need to use ruby_version_is
guards as documented on https://github.com/ruby/spec/blob/master/CONTRIBUTING.md#guards,
because the behavior of previous versions will not change (unless this is decided to be backported, but very unlikely for a new feature, and even then the backport would be done later so the guards would be needed at first).
Updated by Anonymous about 6 years ago
Updated by shuber (Sean Huber) about 6 years ago
Eregon (Benoit Daloze) wrote:
Yes, in such a case you need to useruby_version_is
guards as documented on https://github.com/ruby/spec/blob/master/CONTRIBUTING.md#guards,
because the behavior of previous versions will not change (unless this is decided to be backported, but very unlikely for a new feature, and even then the backport would be done later so the guards would be needed at first).
Perfect thanks @Eregon (Benoit Daloze), pull request updated!
oleynikov (Alexander Oleynikov) wrote:
And I'm not sure why we need to change just #tap and not other methods.
There are some discussions going on about passing arguments whith Symbol#to_proc shorthand: #12115, #15301, etc. Personally I'd rather see one of these implemented. It would also fix this issue.
Thanks for the links to the other discussions @oleynikov, pretty interesting, I'll keep an eye on those as well!
For Kernel#tap
specifically I think it still makes sense to allow it to accept arguments like Kernel#send
since they basically behave the same aside from tap
always returning self
. Relying on the proposals to support Symbol#to_proc
with arguments (which could take awhile until they're actually merged) looks a bit more abstract than it needs to be:
array.tap(:delete, object)
# vs
array.tap(&:delete.(object)) # if that's the syntax they agree on
# vs
array.tap { |a| a.delete(object) } # currently supported
I could get behind something like this too:
array.tap(&:delete, object)
Updated by hsbt (Hiroshi SHIBATA) almost 3 years ago
- Project changed from 14 to Ruby master