I just wanted to apply a binary operation to consecutive elements in an array, eg:
[1, 2, 3, 4].each_cons(2).map { |a, b| a.quo(b) }
#=> [(1/2), (2/3), (3/4)]
This is a contrived example, the operation doesn't really matter.
I was surprised, that I couldn't just write:
[1, 2, 3, 4].each_cons(2).map(&:quo)
#=> NoMethodError: undefined method `quo' for [1, 2]:Array
This is because each_cons
doesn't yield multiple values, but an array containing the values.
It works like this:
def each_cons_arrays
return enum_for(__method__) unless block_given?
yield [1, 2]
yield [2, 3]
yield [3, 4]
end
each_cons_arrays.map(&:quo)
#=> NoMethodError: undefined method `quo' for [1, 2]:Array
And I was hoping for:
def each_cons_values
return enum_for(__method__) unless block_given?
yield 1, 2
yield 2, 3
yield 3, 4
end
each_cons_values.map(&:quo)
#=> [(1/2), (2/3), (3/4)]
What's the rationale behind this? Why could it be preferable to always have an array?
And by the way, with_index
on the other hand does yield multiple values:
[1, 1, 1].each.with_index(2).map(&:quo)
#=> [(1/2), (1/3), (1/4)]
From my experience, it helps to think of multiple values in ruby as an array.
It think of it at as
[1,2,3].each_cons(2) do |iter|
a,b = iter
do_stuff(a,b)
end
If you want to do it like that, I'd add the quo
method to a custom class, and do
class Foobar
def initialize(a,b)
@a = a
@b = b
end
def quo
do_stuff
end
end
[1,2,3]
.each_cons(2)
.map { |a,b| Foobar.new(a,b) }
.map(:quo)
Would that work for your usecase?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.