Bug #15174
closedSorting array of elements using "&:size" block, in which more than 1 element
Description
Example with ranges(first with what defined bug), but also tested on strings, symbols, integers
Good
[1..2].sort { |x| x.size }
[1..2, 4..5].sort { |x| x.size }
[1..2].sort(&:size)
Bad
[1..2, 4..5].sort(&:size)
Traceback (most recent call last):
4: from /home/sviat/.rvm/rubies/ruby-2.6.0-preview2/bin/irb:11:in <main>' 3: from (irb):3 2: from (irb):3:in
sort'
1: from (irb):3:in `size'
ArgumentError (wrong number of arguments (given 1, expected 0))
Tested ruby versions: 2.5.1, 2.6.0-preview2
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
You want sort_by
, not sort
:
[1..2, 4..5].sort_by(&:size)
# => [1..2, 4..5]
The difference in behavior between { |x| x.size }
and (&:size)
is due to how ruby handles Symbol#to_proc
when multiple arguments are yielded. If a block yields multiple arguments, Symbol#to_proc
is the equivalent of first_arg.send(symbol, *remaining_args)
, not first_arg.send(symbol)
or [first_arg, *remaining_args].send(symbol)
. Example:
def b(*a)
p [self, a]
1
end
[1..2, 4..5].sort{|x| x.b}
# => [4..5, 1..2]
# output:
# [1..2, []]
[1..2, 4..5].sort(&:b)
# => [4..5, 1..2]
# output:
# [1..2, [4..5]]
Range#size
does not take an argument, hence the ArgumentError when you are using sort(&:size)
with an array of Range instances.
I believe this behavior is expected (see vm_yield_with_symbol
in vm_insnhelper.c
). However, a more experienced rubyist should probably confirm that.
Updated by nobu (Nobuyoshi Nakada) over 5 years ago
- Status changed from Open to Rejected
An expected behavior.