On Oct 4, 7:04 am, Stefano C. [email protected] wrote:
require ‘generator’
class Array
def (other)
SyncEnumerator.new(self, other).map{|x, y| xy}
end
end
Thanks for the tip on SyncEnumerator.
If a class/module must be opened, I think Enumerator would be better
than Array. Also, I prefer method names over operators in this case,
but that’s a personal preference:
require ‘generator’
require ‘pp’
module Enumerable
def cartesian_product other
self.inject([]) {|result, a| other.each {|b| result << [a, b] };
result }
end
def dot_product other
SyncEnumerator.new(self, other).inject(0) {|s,v| s += v[0]*v[1];
s }
end
def mmap *others, &f
SyncEnumerator.new(self, *others).map(&f)
end
def cross_product other
# exercise for reader
end
end
x = [1, 2, 3]
y = [1, 10, 100]
pp x.dot_product(y)
puts '-'10
pp x.mmap(y) {|a,b| ab }
pp x.mmap(y, [1, 2, 4]) {|a,b,c| abc }
puts ‘-’*10
pp x.cartesian_product(y)
puts ‘-’*10
BTW, with the mmap call above, I originally got bit by a scope issue
because I named the local variables |x,y|, so the assignment to the
block variables overwrote x & y in the outer scope
Personally, I’d prefer to not open a class/module and simply define
functions.
def cartesian_product enum1, enum2
enum1.inject([]) {|result, a| enum2.each {|b| result << [a, b] };
result }
end
def dot_product enum1, enum2
SyncEnumerator.new(enum1, enum2).inject(0) {|s,v| s += v[0]*v[1];
s }
end
def mmap *enums, &f
SyncEnumerator.new(*enums).map(&f)
end
pp dot_product(x, y)
puts '-'10
pp mmap(x, y) {|a,b| ab }
pp mmap(x, y, [1, 2, 4]) {|a,b,c| abc }
puts ‘-’*10
pp cartesian_product(x, y)