injectつづき
http://d.hatena.ne.jp/ha-tan/20060717
この実装は素敵だなぁ.素敵な記法は貪欲に吸収.
そうそう,Haskellには,foldlにつづきfoldl1というものがある.これは,injectでいうとこの初期値?が無いかたち.わかり易い例を示すと,こうなる.
Hugs.Base> foldl (+) 0 [1 .. 10] 55 Hugs.Base> foldl1 (+) [1 .. 10] 55
んじゃそれをRubyでやったらば?
とりあえずは何も考えず.
module Enumerable def inject1 result = self[0] self.each_index do |i| i += 1 break if i >= size result = yield(result, self[i]) end result end end (1..10).to_a.inject1{|r, e| r += e} => 55
これは俗に言う,汚い実装.breakを使うと突然美しさが損なわれる気がする.
breakを使わない方向で考える.
module Enumerable def inject1 result = (foo = self.dup).shift foo.each do |e| result = yield(result, e) end return result end end
dupってアリ?でも,どうせならinjectを呼びたい.貪欲に.
module Enumerable def inject1 result = (foo = self.dup).shift return foo.inject(result){|result, elem| yield(result, elem)} end end
まだこっちのがカッコいい.
dupを使わない方向で考える.
module Enumerable def inject1 result = self[0] for i in (1 ... self.size) result = yield(result, self[i]) end return result end end
for文.たぶん,Rubyやってて初めて書いた.あぁ,ってかこっちでもinject呼んでやれば良いじゃない.
module Enumerable def inject1 self[1 ... size].inject(self[0]){|result, elem| yield(result, elem)} end end
やった1行だ.
追記
プログラミング言語 Ruby リファレンスマニュアルを見る以上,
このモジュールのメソッドは全て each を用いて定義されてい
なければならないのかしらという強迫観念にかられ(そんなことはない!),かつid:ha-tanさんのまねごとをしつつ,eachを用い,[]など配列に依存するものを用いず,考える.
module Enumerable def inject1 result = nil each do |elem| if result == nil result = elem else result = yield(result, elem) end end result end end
ha-tanさんのと殆ど変わらない.てかこのifをどーにかできないものか.と思うと同時に,こんなことばかりしてるからレポートが進まないのだと己に言い聞かせながらも,まだ考える.だけどもうこれ以上考えられないんで,とりあえず今日は終わり.
追記2
b2oxさんのコメントより,せめてif-else-endに書き直しました.