#tqrk03 で発表した内容がアレだったので、無限ストリームをrubyでやった
東急Ruby会議(#tqrk03)に遊びに行ったら、@tadasyの罠にハメられて無意味に3分LTすることになった。
なんの準備もしてなかったので、空気を読まずに前の記事に書いたHaskellがすげえっていう話をすることにした。
だってRubyわかんねーんだもん。
んで、みんな酒が入った勢いで笑ってたが何一つ意味分からなかったと思われるので、無限ストリームのやつをRubyに移植した。私はRubyまったくわからないので、なんかおかしな書き方だったら教えてほしい。
プログラムだけ書いて力尽きたので、解説が必要な人はSICPを読んでほしい。
class Stream def initialize(car, &cdr) @car = car @cdr = cdr end def car @car end def cdr @cdr.call end def take(n) (n == 0) ? [] : (cdr.nil?) ? [@car] : cdr.take(n-1).unshift(@car) end def ref(n) (n == 0) ? @car : cdr.nil? ? nil : cdr.ref(n-1) end def map(&f) Stream.new(f.call(@car)) { cdr.map(&f) } end end class << Stream def zipWith(s1, s2, &f) car = f.call(s1.car, s2.car) new(car) { zipWith(s1.cdr, s2.cdr, &f) } end def repeat(x) new(x) { repeat(x) } end def integerStartinFrom(n) new(n) { integerStartinFrom(n+1) } end def integer integerStartinFrom(1) end def add(s1, s2) zipWith(s1, s2) {|a, b| a + b } end def mul(s1, s2) zipWith(s1, s2) {|a, b| a * b } end def partialSums(s) new(s.car) { add(repeat(s.car), partialSums(s.cdr)) } end end class Series end class << Series def integrate(s) Stream.zipWith(s, Stream.integer) {|a, b| a / b } end def exp Stream.new(1.0) { integrate(exp) } end def cos Stream.new(1.0) { integrate(sin.map{|a| -a }) } end def sin Stream.new(0.0) { integrate(cos) } end end def sum(array) array.inject(0) {|a, b| a + b } end ones = Stream.repeat(1) integer = Stream.integer p ones.take(10) p integer.take(10) p Stream.add(ones, integer).take(10) p Stream.mul(integer, integer).take(10) p Stream.partialSums(integer).take(10) p Stream.partialSums(Series.exp).ref(10) p Math.exp(1) p Stream.partialSums(Series.sin).ref(10) p Math.sin(1) p Stream.partialSums(Series.cos).ref(10) p Math.cos(1)