return, break, next の使い方

ループ処理や関数を書いていて、`return` , `break` , `next` をなんとなく使っていたことに気づきました。しっかりと挙動を理解して使っていきたいので、違いをまとめておきます。  

ざっくりいうと、`return` は**関数そのものを終了**します。  
`break` と `next` は**ループ内で使う**ものです。`break` は**ループそのものを抜け**、`next` は**その回だけループを抜けます。**  

以下で例とともに使い方をまとめます。  

## 目次

[1. return](#1-return)
[2. break](#2-break)
[3. next](#3-next)

## 1. return

returnは関数内に書きます。returnを書いた箇所で**関数自体を終了し、その関数の呼び出し元に戻ります。**

```ruby
def hello
  puts 'こんにちは'
  return
  puts 'お元気ですか？' # 実行されない
end

hello # 関数呼び出し
puts 'さようなら' # 実行される
```

出力結果：

```bash
こんにちは
さようなら
```

この例では、`return` の時点で関数 `hello` が終了するため、その後の `puts 'お元気ですか？'` は実行されません。  
そして `hello` 関数の呼び出し元に処理が戻るため、次の `puts 'さようなら'` が実行されます。  

### return を関数内の `each` や `if` の中に書く

`return` は、関数内の `each` などのループ処理や `if` 文の中にも書くことができます。  
関数内の `each` や `if` 文の中で `return` した場合、その後の関数内の処理は、 `each` や `if` 文の**外に書いてあったとしても実行されません。**  
繰り返しになりますが、`return` は**関数自体を終了する**ためです。  

以下は、配列内の一番初めの偶数を見つける関数の例です。  
一番初めの偶数を見つけたら、その時点で関数が終了します。  

```ruby
def find_even(nums)
  nums.each do |num|
    if (num % 2).zero?
      puts "#{num}は偶数です！！"
      return # 偶数を見つけたら return
    else
      puts "#{num}は奇数です"
    end
  end
  puts '関数の最後です' # 実行されない
end

find_even([5, 17, 8, 20, 121]) # 関数呼び出し
puts '関数の次の処理です' # 実行される
```

出力結果：

```bash
5は奇数です
17は奇数です
8は偶数です！！
関数の次の処理です
```

ここでは `find_even` 関数内の `each`、さらに `if` 文の中に `return` を書いています。関数の最後の `puts '関数の最後です'` は、`each` や `if` 文の外に書いてありますが、`return` で関数自体が終了されるため実行されません。  
`return` の後は、関数の呼び出し元に処理が戻るため、その後の `puts '関数の次の処理です'` が実行されます。  

## 2. break

`break` は、`loop` や `while` や `times` など、ループ処理の中で使います。  
`break` は**ループそのものを抜けます**が、関数自体は終了しません。  

先ほどと同じ、配列内の一番初めの偶数を見つける関数の例です。  

```ruby
def find_even(nums)
  nums.each do |num|
    if (num % 2).zero?
      puts "#{num}は偶数です！！"
      break # 偶数を見つけたら break
    else
      puts "#{num}は奇数です"
    end
  end
  puts '関数の最後です' # 実行される
end

find_even([5, 17, 8, 20, 121]) # 関数呼び出し
```

出力結果：

```bash
5は奇数です
17は奇数です
8は偶数です！！
関数の最後です
```

先ほどの `return` とは違い、関数の最後の `puts '関数の最後です'` は実行されます。

また２重ループの内側で `break` を使った場合は、その内側のループのみを抜けます。

```ruby
def double_loop
  (1..4).each do |x|
    (1..4).each do |y|
      if y == 3
        break # y == 3 で break
      end
      puts "内側ループ x: #{x} y: #{y}"
    end
    puts "外側ループ x: #{x}"
  end
  puts '関数の最後です' # 実行される
end

double_loop # 関数呼び出し
```

出力結果：

```bash
内側ループ x: 1 y: 1
内側ループ x: 1 y: 2
外側ループ x: 1
内側ループ x: 2 y: 1
内側ループ x: 2 y: 2
外側ループ x: 2
内側ループ x: 3 y: 1
内側ループ x: 3 y: 2
外側ループ x: 3
内側ループ x: 4 y: 1
内側ループ x: 4 y: 2
外側ループ x: 4
関数の最後です
```

内側のループで `y == 3` になった時点で、 `break` により内側のループが終了しています。ですが、その後 `x` の数は増えていき、外側のループは終わらず続いていることが分かります。  

## 3. next

`next` も `break` と同様に、`loop` や `while` や `times` など、ループ処理の中で使います。  
`break` との違いは、ループそのものではなく**その回のループだけを抜ける**ということです。  

Rubyの `next` は、他言語の `continue` に相当するものです。  

以下は、配列内の数が偶数の場合だけ `puts` を実行する関数です。奇数の場合は `next` としてその回のループをスキップしています。  

```ruby
def find_even(nums)
  nums.each do |num|
    if (num % 2).zero?
      puts "#{num}は偶数です！！"
    else
      next # 奇数の場合は next
    end
  end
  puts '関数の最後です' # 実行される
end

find_even([5, 17, 8, 20, 121]) # 関数呼び出し
```

出力結果：

```bash
8は偶数です！！
20は偶数です！！
関数の最後です
```

また２重ループの内側で `next` を使った場合は、その内側のループに関して、次のループへスキップします。

```ruby
def double_loop
  (1..4).each do |x|
    (1..4).each do |y|
      if y == 3 # y == 3 で next
        next
      end
      puts "内側ループ x: #{x} y: #{y}"
    end
    puts "外側ループ x: #{x}"
  end
  puts '関数の最後です'
end

double_loop # 関数呼び出し
```

出力結果：

```bash
内側ループ x: 1 y: 1
内側ループ x: 1 y: 2
内側ループ x: 1 y: 4
外側ループ x: 1
内側ループ x: 2 y: 1
内側ループ x: 2 y: 2
内側ループ x: 2 y: 4
外側ループ x: 2
内側ループ x: 3 y: 1
内側ループ x: 3 y: 2
内側ループ x: 3 y: 4
外側ループ x: 3
内側ループ x: 4 y: 1
内側ループ x: 4 y: 2
内側ループ x: 4 y: 4
外側ループ x: 4
関数の最後です
```

内側のループで `y == 3` の場合のみ `next` でループをスキップしています。一回スキップしているだけなので、次の `y == 4` の時には実行されていますし、その後 `x` の数は増えているので外側のループも続いていることが分かります。  

以上となります。  
しっかりと挙動を理解して使っていきたいです。