1. genya0407

    No comment

    genya0407
Changes in body
Source | HTML | Preview
@@ -1,131 +1,131 @@
Rubyのブロックを雰囲気で使ってる人に向けて、ブロックの使い方を整理する。
## ブロックとはなにか
ブロックは「処理の集合体」です。無名関数とかラムダ式とかクロージャのようなものです。
例:
```ruby
# { ... } がブロック
[1,2,3,4].map { |e| e + 1 }
# do ... endがブロック
[1,2,3,4].map do |e|
e + 1
end
```
-**ブロックは「メソッドに渡す」という形式でしか存在できません**。なので、例えば以下のコードはSnytax Errorになります。
+**ブロックは「メソッドに渡す」という形式でしか存在できません**。なので、例えば以下のコードはSyntax Errorになります。
```ruby
a = { |e| e + 1 }
a = do |e|
e + 1
end
```
## ブロック付きメソッド呼び出し
メソッドがブロックを受け取る方法を説明します。
### `yield`
1つ目のやりかたは、`yield`を使うことです。
例:
```ruby
def hoge
yield(100)
end
hoge { |e| e + 1 } # => 101
```
ちょっと分かりづらいですが、`yield`がブロックを「起動」していると思ってください。`yield`の引数がブロックの引数になります。
ちなみに、ブロックとは別に引数を渡すことができます。
```ruby
def hoge(a)
yield(a)
end
hoge(1000) { |e| e + 1 } # => 1001
```
### `&block`
2つ目のやりかたは、`&block`引数を使うことです。
```ruby
def hoge(&block)
block.call(100)
end
hoge { |e| e + 1 } # => 101
```
このように`&block`という引数を宣言すると、ブロックが`block`変数に代入されます。そして、`block.call`メソッドを呼ぶと、ブロックの処理が実行されます。直感的ですね。
この場合も、ブロックとは別に引数を渡すことができます。
```ruby
def hoge(a, &block)
block.call(a)
end
hoge(1000) { |e| e + 1 } # => 1001
```
## ブロックオブジェクト(`Proc`)
「さっき『ブロックは変数に代入できない』って言ったじゃん!」と思った人がいると思います。
実は`block`に入っているのはブロックではなく「`Proc`オブジェクト」です。
`Proc`オブジェクトは以下のように生成できます。
```ruby
blk1 = Proc.new { |e| e + 1 }
blk1.call(100) # => 101
blk2 = proc { |e| e + 2 }
blk2.call(100) # => 102
```
`Proc`はオブジェクトなので、変数に代入できます。
つまり、メソッドが`&block`変数でブロックを受けると、上のような処理が走ってブロックをオブジェクトにしているということですね。
## `Proc`からブロックへの変換
`Proc`をブロックとしてメソッドに渡したい気持ちになることがあります。
```ruby
plus_100 = proc { |e| e + 100 }
[1,2,3].map(plus_100) # => Error!
```
しかしこれはエラーになります。なぜなら`plus_100`はProcオブジェクトであってブロックではないからです。
Procオブジェクトをブロックに変換するためには`&`を使います。
```ruby
plus_100 = proc { |e| e + 100 }
[1,2,3].map(&plus_100) # => [101, 102, 103]
```
このように、`&`をProcオブジェクトの前につけることによって、Procオブジェクトを「展開」し、ブロックとしてメソッドに渡すことができます。
## まとめ
- ブロックとは処理の集合体である
- ブロックは「メソッド呼び出しに渡す」という使い方しかできない
- メソッドがブロックを受け取る方法は2つある
- `yield` 命令
- `&block` 引数
- ブロックをオブジェクトに変換すると`Proc`になる
- `block = Proc.new { |e| e + 1 }`
- `block = proc { |e| e + 1 }`
- `Proc`をブロックに変換するには`&`を使う
- `array.map(&block)`