1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Ruby】whileの戻り値を正しく把握していなかった

Last updated at Posted at 2024-08-07

素のRubyを用いてちょっとした業務カイゼンアプリを作ってたのだが、そのときにほんの少しだけ当たった問題

※ 鬼基本的な内容です

whilenilを返します

※単一ファイルで書かれたスクリプトを想定しています

「渡ってきた日付(dateオブジェクト)が土日祝のいずれかに当てはまるかを判定し、当てはまる場合は平日になるまで1日ずつ日付を加算する」という処理を作っていた

  • 日付を加算するにはdateオブジェクトに+ 1をしていけばよい
  • 土日の判定はDateクラスにあるsaturday?sunday?が、日付が土日の場合にtrueを返す
  • 日本の祝日判定はHolidayJpというGemのメソッドを使えば同じように祝日に当てはまるときtrueを返す
  • 上記がtrueのときに日付を1日加算したい

条件がtrueのときに処理をループさせることができるwhile使えばいいのでは? と思い以下のような処理を書いた

while day.saturday? ||
      day.sunday? ||
      HolidayJp.holiday?(day)
    day += 1
end

実際に試してみる

# 日曜日
day = Date.new(2024, 8, 11)
=> #<Date: 2024-08-11 ((2460534j,0s,0n),+0s,2299161j)>

while day.saturday? ||
      day.sunday? ||
      HolidayJp.holiday?(day)
    day += 1
end

p day
=> #<Date: 2024-08-12 ((2460535j,0s,0n),+0s,2299161j)>

# ちゃんと平日である8月12日㈪が返ってきた!

期待した値が返ってきたのでOK

ただこの処理はスクリプト内のいたるところで使用していたので、メソッドにしたいと思いメソッド化した

# 日曜日
day = Date.new(2024, 8, 11)

def check_weekend_return_weekday(day)
  while day.saturday? ||
        day.sunday? ||
        HolidayJp.holiday?(day)
    day += 1
  end
end

weekday = check_weekend_return_weekday(day)
p weekday

「ま、ふつうになんも問題ないやろ」と思ってたら。。。。。。。。。

nil

ohhhhhhhhhhhhhhhhhhhhhhhhh

なぜだ、、、と思ってリファレンス見てみたら普通に答え書いてあった

while は nil を返します

公式: 制御構造 (Ruby 3.3 リファレンスマニュアル)

Rubyはメソッドの最後に評価された式が戻り値になるのでwhile自体がnilを返すならnilが返ってくるのは当たり前だ。。。。

メソッド内でwhileで処理した値を返したい場合はbreakか戻り値を明示させよう

なので修正
公式には以下のように書いてある

また、引数を伴った break により while 式の戻り値をその値にすることもできます。

公式: 制御構造 (Ruby 3.3 リファレンスマニュアル)

というわけで返したい値にbreakを明示させておこう

# 日曜日
day = Date.new(2024, 8, 11)

def check_weekend_return_weekday(day)
  while day.saturday? ||
        day.sunday? ||
        HolidayJp.holiday?(day)
    break day += 1 # breakを明示
  end
end

weekday = check_weekend_return_weekday(day)
p weekday

=> #<Date: 2024-08-12 ((2460535j,0s,0n),+0s,2299161j)>

ちゃんと返ってきた!

当然だがbreak使わないでメソッドの最後に戻り値を明示させるだけでもOK

# 日曜日
day = Date.new(2024, 8, 11)

def check_weekend_return_weekday(day)
    while day.saturday? ||
          day.sunday? ||
          HolidayJp.holiday?(day)
      day += 1
    end
  day # メソッドの最後に戻り値を明示
end

weekday = check_weekend_return_weekday(day)
p weekday

=> #<Date: 2024-08-12 ((2460535j,0s,0n),+0s,2299161j)>

基本的なことだが忘れないようにしよう

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?