(ruby)(Rubyのイテレーターの基礎をまとめてみた)

eachなどでよく利用されている便利なイテレーターですが
いざ自分でそういったものを定義してみようとなると
「ワケガワカラン・・・」と挫折しそうになってしまうので
出来る限り噛み砕いて理解してみることにしました

これは、それをまとめた物ですので 内容に誤りがあるかもしれません
また、見やすくするため、理解しやすくするため
というかそもそも私のクセのため
省略可能な括弧もあえて書いています
あらかじめご了承ください

まずイテレーターを実現するための 基礎となる形は
def sample001()
	yield()
end

sample001(){
	puts('hello')
}
hello
になります
つまり メソッド定義の yield()の部分が
呼び出し側のブロックの部分と「置き換えられて」実行されます
(ただし これは反復処理をしてないので まだイテレーターとは呼べません)

「置き換えられて」ということなので
ブロックの最終行の結果が yield()の戻り値になります
つまり「ブロック内の結果を元に処理をすることも可能」という事になります
def sample002()
	if yield() then
		puts('true')
		return('true')
	else
		puts('false')
		return('false')
	end
end

puts('>>' << sample002(){100.even?})
puts('>>' << sample002(){111.even?})
true
>>true
false
>>false
続いて、ブロックの方へ値を値を渡す方法です
これが出来ると何が出来るのかというと
ブロック側で値の編集などが出来るようになります
def sample003()
	puts(yield('hello'))
end

sample003(){|x|
	'>>>' << x << '<<<'
}
>>>hello<<<
ブロック側に複数個の値を渡したい場合は
このようにすれば二つ三つと値を渡す事が出来ます
def sample004()
	puts(yield('hello','world'))
end

sample004(){|x,y|
	'>>>' << x << '<<< >>>' << y << '<<<'
}
>>>hello<<< >>>world<<<
これらは特殊な動きをするとはいえ
あくまでも メソッド定義の一つなんですから
呼び出し側から 引数で値を渡す事も出来ます
(そして、配列の要素分反復するので、ここで初めてイテレーターと呼べる形になります)
def sample005(val)
	val.each{|dat|
		if yield(dat) then
			puts('' << dat.to_s << ' is even')
		else
			puts('' << dat.to_s << ' is odd')
		end
	}
end

sample005([5,10,7,3,1,2,8,15,16]){|x|
	x.even?
}
5 is odd
10 is even
7 is odd
3 is odd
1 is odd
2 is even
8 is even
15 is odd
16 is even
ここまでは 普通にメソッド定義をしただけでしたが
今度は 既に有るクラスに機能追加する方法を考えてみます
class Array
	def enum_check(str = '')
		c1 = 0
		c2 = 0
		puts('>  ' << str << '  <')
		self.each{|dat|
			if yield(dat) then
				c1 += 1
				puts('' << dat.to_s << ' is true')
			else
				c2 += 1
				puts('' << dat.to_s << ' is false')
			end
		}
		puts('true=' << c1.to_s() << '  false=' << c2.to_s())
	end
end

[5,10,7,3,1,2,8,15,16].enum_check('greater than 5'){|x| x>5}
>  greater than 5  <
5 is false
10 is true
7 is true
3 is false
1 is false
2 is false
8 is true
15 is true
16 is true
true=5  false=4
このサンプルの場合だと
配列の各要素がブロック内の条件を満たしているかどうかを調べて列挙し
真偽の数もカウントして表示します