Rangeの積

「Rangeの積を求める」をやってみたにはコメントしたのだが、ちゃんと実装するのは面倒そうと思っていた。
で、いざ実装してみると、やっぱり面倒だった・・。

to_aして、変換できるクラス(succが定義されているクラス)ならそのArrayの積を取る。
効率は悪そうだけど、ここは簡単。
変換できなかったら終端見ながら範囲の大小比較。


そもそも
("a".."z") と ("aa".."zz")の積はどうあるべきか。空でいいのか。
to_aして積を取ると空になる。要素を列挙して比較してみると妥当な結果に見える。
しかし、
("a".."z").include? "bb"
はtrue!*1
(1..3).include? 1.5
がtrueになるのは許せるのだが・・*2


ニーズはありそうなのにRangeの積が標準ライブラリで実装されていない理由がなんとなくわかる気がする。


class Range
def &(dest)
begin
w=self.to_a&dest.to_a
w.empty? ?nil:w.min..w.max
rescue TypeError
return nil if self.begin > dest.end or dest.begin > self.end
return nil if self.begin == dest.end and dest.exclude_end?
return nil if dest.begin == self.end and self.exclude_end?
first=[self.begin, dest.begin].max
if self.end < dest.end
last=self.end;exclude_end=self.exclude_end?
elsif dest.end < self.end
last=dest.end;exclude_end=dest.exclude_end?
else # dest.max==self.max
last=self.end;exclude_end=(self.exclude_end? or dest.exclude_end?)
end
Range.new(first,last,exclude_end)
end
end
end

*1: ("a".."z").to_a.include? "bb" はfalseになる

*2:というか、trueになって欲しい