Bug #13592
closed
Enumerable#reduce with symbol does not respect method visibility
Added by americodls (Americo Duarte) over 7 years ago.
Updated over 7 years ago.
ruby -v:
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin15]
[ruby-core:81349]
Description
When use reduce with symbol, I expect the symbol is called in object but respecting the method visibility.
Example with source code written in a file.
Fixnum.instance_eval do
private :+
end
p [1,2,3].reduce(:+)
The behavior in IRB is different.
irb(main):001:0> [1,2,3].reduce(:+)
=> 6
irb(main):002:0> Fixnum.instance_eval do
irb(main):003:1* private :+
irb(main):004:1> end
=> Fixnum
irb(main):005:0>
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/irb/input-method.rb:154:in `gets': private method `+' called for 4:Fixnum (NoMethodError)
Now, I am confused. Those behaviors are expected? In doc this is not clear.
Sorry, ignore the IRB thing. But my question about the reduce still valid.
- Description updated (diff)
- Status changed from Open to Rejected
The proc returned by Symbol#to_proc
is equivalent to proc {|recv, *args| recv.__send__(self, *args)}
.
So it can call private methods too.
- Status changed from Rejected to Feedback
Please, reconsider. Look this example:
irb(main):092:0> :puts.to_proc.call("")
NoMethodError: private method `puts' called for "":String
nobu (Nobuyoshi Nakada) wrote:
The proc returned by Symbol#to_proc
is equivalent to proc {|recv, *args| recv.__send__(self, *args)}
.
So it can call private methods too.
- Status changed from Feedback to Open
reduce(&:+) is different from
reduce(:+), this one has nothing to do with :+.to_proc
reduce/inject with symbol param does call the method internally without checking if its private or not
This is exactly what I am saying.
This behavior of reduce
is unpredictable and different of the another Enumerable
methods.
Users will expect that symbol argument is converted in proc and then applied to object.
reduce
(since v1.8.7) is older than public_send
(since 1.9.1), maybe this is the reason of the reduce
works like that.
But these days, as we have public_send
and the :symbol.to_proc
works similar to public_send
I think make sense the reduce
works with :symbol.to_proc
, and not reaching private methods.
Hanmac (Hans Mackowiak) wrote:
reduce(&:+) is different from
reduce(:+), this one has nothing to do with :+.to_proc
reduce/inject with symbol param does call the method internally without checking if its private or not
i think you still mix reduce(&:+) with reduce(:+)
both are two totally different ways to call this method.
(the later doesn't go the way with a Proc object)
because reduce("+") works too
- Status changed from Open to Closed
Applied in changeset trunk|r58871.
enum.c: respect method visibility
- enum.c (ary_inject_op): should respect method visibility, do not
optimize uncallable method. [ruby-core:81349] [Bug #13592]
- Backport changed from 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN to 2.2: WONTFIX, 2.3: WONTFIX, 2.4: UNKNOWN
memo: I think this is a bug, but it may cause some compatibility problems to change the behavior in teeny release, then I decided not to backport this to ruby_2_3.
Also available in: Atom
PDF
Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0