I have been learning ruby for the last few weeks and I came across something like:
array = [10, 20, 20];
array.reduce(:^)
# => 10
which evaluated to 10.
The purpose of the code was to find an element with an odd number of occurrences within a sequence such as [10, 20, 20]
.
Does anyone have a relatively simple explanation of how this works?
array = [10, 20, 20];
array.reduce(:^)
#=> 10
produces the same result as
array.reduce { |t,n| t^n }
#=> 10
Let's add a puts
statement to see what is happening.
array.reduce do |t,n|
puts "t = #{t}, n = #{n}, t^n = #{t^n}"
t^n
end
# t = 10, n = 20, t^n = 30
# t = 30, n = 20, t^n = 10
#=> 10
When Enumerable#reduce is not given an argument the "memo" (the block variablet
) is set equal to the first element of the receiver (10
) and the first element passed to the block is the second element of the receiver, 20
.
Fixnum#^ is the bitwise "exclusive-or" operator (XOR).
When t #=> 10
and (the first) n #=> 20
is passed to the block:
t^n #=> 30
because
10.to_s(2) #=> "01010"
20.to_s(2) #=> "10100"
-----
(10^20).to_s(2) #=> "11110"
"11110".to_i(2) #=> 30
10^20 #=> 30
When t #=> 30
and (the second) n #=> 20
is passed to the block:
t^n #=> 10
because
30.to_s(2) #=> "11110"
20.to_s(2) #=> "10100"
-----
(30^20).to_s(2) #=> "01010"
"1010".to_i(2) #=> 10
(30^20) #=> 10