Rubyでクロージャを使いたい(導入編)

Procクラスとかラムダ式とかクロージャとかって知識としては知ってるけど、実際に使うことってあんまりない。というか使う腕がない、でも使いこなしたい。というわけで今回は初歩的なサンプルをいくつか作ってみる。ちなみにクロージャやProcクラスそのものについての説明はありません。以下のリンクが参考になるかも。

[クロージャ-Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%B8%E3%83%A3)
[[Ruby] ブロックやProcの使いどころを理解する](http://qiita.com/kidach1/items/15cfee9ec66804c3afd2)

## サンプル1： カウンター
指定回数実行するとfalseを返し、回数に届くまではtrueを返すインスタンスを作成したい。例えば以下のような感じ。

count_5は4回目まではcallするたびにtrueを返すが、5回目からはfalseを返す。

```rb
count_5.call #true
count_5.call #true
count_5.call #true
count_5.call #true
count_5.call #false
count_5.call #false
```

これを実現するには、まずは次のようなcounterメソッドを定義する

```rb
def counter(n)
	count = n
	->{
		count -= 1
		count > 0
	}
end
```

そしてcounterメソッドを参照する変数を宣言する。

```rb
count_5 = counter 5
```

falseを返すようになるタイミングはcounterメソッドの引数で指定できるようにしてある。以下のサンプルでは3回と5回のカウンターを作成して使用している。

```rb
#counterメソッドの宣言
def counter(n)
	count = n
	->{
		count -= 1
		count > 0
	}
end

count_3 = counter 3 
count_5 = counter 5

p count_3.call
p count_3.call
p count_3.call
p count_3.call

while count_5.call do
	p "hello"
end
```

結果

```rb
true
true
false
false
"hello"
"hello"
"hello"
"hello"
```

実用性は特にないけどサンプルとしては分かりやすいと思う。

## サンプル2：素数を順番に数える

callするたびに特定の整数nよりも大きい素数を順番に返すインスタンスを作成したい。例えば次のような感じ

prime_number_over_10はcallするたびに10より大きい素数を順番に返す。

```rb
prime_count_over_10.call #11
prime_count_over_10.call #13
prime_count_over_10.call #17
prime_count_over_10.call #19
```

まずは以下のようなprime_countメソッドを定義する。ちなみにPrime#primer?メソッドは引数が素数ならtrueを返す。

```rb
require 'prime'

def prime_count(n)
	count ||= n
	->{
		count += 1
		while !Prime.prime?(count)
			count += 1
		end
		return count
	}
end
```

そしてprime_countメソッドを参照する変数を宣言する。

```rb
prime_count_over_10 = prime_count 10
```

prime_count_over_10はprime_countメソッドの引数で指定した整数(今回は10)よりも大きい素数を順番に返す。以下のサンプルでは10より大きい素数と1000より大きい素数をそれぞれ順番に5個ずつ出力している。

```rb
require 'prime'

def prime_count(n)
    count ||= n
    ->{
        count += 1
        while !Prime.prime?(count)
            count += 1
        end
        return count
    }
end

prime_count_over_10 = prime_count 10
prime_count_over_1000 = prime_count 1000

5.times do p prime_count_over_10.call end

print "\n"

5.times do p prime_count_over_1000.call end
```

結果

```rb
11
13
17
19
23

1009
1013
1019
1021
1031
```

このサンプルで行ったようなことは、Prime#モジュールのメソッドを使用すれば簡単に実装できるんだけど、今回はあくまでも練習なのでPrime#モジュールの使用は最低限に控えてあります。

## サンプル3： ON・OFFスイッチ
callするたびにtrueとfalseを交互に返すインスタンスを作成したい。具体的には以下のような感じ

on_off_switchは奇数回目のcallではtrueを返すが、偶数回目のcallではfalseを返す。

```rb
on_off_switch.call #true
on_off_switch.call #false
on_off_switch.call #true
on_off_switch.call #false
```

これを実現するために、まずは以下のようなメソッドを作成する。

```rb
def onoff
	n = false
	->{
		n = !n
	}
end

```

そして上記のonoffメソッドを参照する変数を宣言する。

```rb
on_off_switch = onoff
```

以下の例では、on_off_switchとサンプル2のprime_countを使用して、100以上の素数を小さい順から一つ飛ばしで10個出力している

```rb
require 'prime'

def prime_count(n)
	count ||= n
	->{
		count += 1
		while !Prime.prime?(count)
			count += 1
		end
		return count
	}
end

def onoff
	n = false
	->{n = !n}
end

prime_count_over_100 = prime_count 100
on_off_switch = onoff

20.times do
	prime_number = prime_count_over_100.call
	p prime_number if on_off_switch.call
end
```

結果

```rb

101
107
113
131
139
151
163
173
181
193
```

次はもう少し実用的なサンプルを作る予定。