サーチ…


if、elsif、else、end

Rubyは、 endキーワードで終わる、分岐論理のための期待されるifelse式を提供します:

# Simulate flipping a coin
result = [:heads, :tails].sample

if result == :heads
  puts 'The coin-toss came up "heads"'
else
  puts 'The coin-toss came up "tails"'
end

Rubyでは、 if文は値に評価される式であり、結果は変数に代入できます。

status = if age < 18
           :minor
         else
           :adult
         end

RubyはCスタイルの三項演算子も提供しています( 詳細はこちらを参照 )。

some_statement ? if_true : if_false  

つまり、if-elseを使用した上記の例は、次のように書くこともできます。

status = age < 18 ? :minor : :adult

さらに、Rubyはelsifキーワードを提供しています。これは、追加の分岐ロジックを有効にするための式を受け入れます:

label = if shirt_size == :s
          'small'
        elsif shirt_size == :m
          'medium'
        elsif shirt_size == :l
          'large'
        else
          'unknown size'
        end

if / elsifチェーンの条件が真でなく、 else節がない場合、式はnilと評価されます。 nil.to_sは空文字列なので、 nil.to_sは文字列補間の中で便利です:

"user#{'s' if @users.size != 1}"

真実と偽の価値

Rubyでは、「偽」とみなされる正確に2つの値があり、 if式の条件としてテストされたときにfalseを返します。彼らです:

  • nil
  • ブール値false

他のすべての値は、以下を含む「真実」とみなされます。

  • 0 - 数値ゼロ(整数またはその他)
  • "" - 空文字列
  • "\n" - 空白のみを含む文字"\n"
  • [] - 空の配列
  • {} - 空のハッシュ

例えば、次のコードを考えてみましょう:

def check_truthy(var_name, var)
  is_truthy = var ? "truthy" : "falsy"
  puts "#{var_name} is #{is_truthy}"
end

check_truthy("false", false)
check_truthy("nil", nil)
check_truthy("0", 0)
check_truthy("empty string", "")
check_truthy("\\n", "\n")
check_truthy("empty array", [])
check_truthy("empty hash", {})

出力:

false is falsy
nil is falsy
0 is truthy
empty string is truthy
\n is truthy
empty array is truthy
empty hash is truthy

〜まで、

whileループは、指定された条件が満たされている間にブロックを実行します。

i = 0
while i < 5
  puts "Iteration ##{i}"
  i +=1
end

untilループは、条件がfalseの間にブロックを実行します。

i = 0
until i == 5
  puts "Iteration ##{i}"
  i +=1
end

インラインif / unless

一般的なパターンは、インラインで、または末尾を使用することであるif又はunless

puts "x is less than 5" if x < 5

これは条件付き修飾語として知られており、簡単なガードコードと早期返品を追加する便利な方法です:

def save_to_file(data, filename)
  raise "no filename given" if filename.empty?
  return false unless data.valid?

  File.write(filename, data)
end

これらの修飾子にelse節を追加することはできません。また、一般的にメインロジック内で条件修飾子を使用することはお勧めしません。複雑なコードのif 、通常のifelsifelse代わりに使用する必要があります。

限り

一般的なステートメントはif !(some condition)です。 Rubyは、 unlessステートメントの代替案を提供しています。

構造体は、条件が負であることを除いて、 if文とまったく同じです。また、 unless文はelsifサポートしていませんが、 elseサポートしていelse

# Prints not inclusive
unless 'hellow'.include?('all')
  puts 'not inclusive'
end

ケースステートメント

Rubyはswitch文にcaseキーワードを使用します。

Ruby Docs

case文は、 case引数の位置にあるオプションの条件と、 when節の0個以上の条件から構成されます。条件に一致する最初のwhen句(または条件がnullの場合はブール値の真理値に評価する)が「勝ち」、そのコードスタンザが実行されます。 case文の値は成功したwhen節の値です。そうした節がない場合はnilです。

case文は、 else節で終了することができelse 。ステートメントがカンマで区切られた複数の候補値を持つことができるそれぞれのwhen

例:

case x
when 1,2,3
  puts "1, 2, or 3"
when 10
  puts "10"
else
  puts "Some other number"
end

短いバージョン:

case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"
end

case節の値は、各when節で===メソッド(not == )を使用して一致します。したがって、さまざまな種類のオブジェクトで使用できます。

caseステートメントは、 範囲で使用できます

case 17
when 13..19
  puts "teenager"
end

case文はRegexpで使うことができます

case "google"
when /oo/
  puts "word contains oo"
end

case文は、 Procまたはlambdaで使用できます。

case 44
when -> (n) { n.even? or n < 0 }
  puts "even or less than zero"
end

クラスでcaseステートメントを使用できます。

case x
when Integer
  puts "It's an integer"
when String
  puts "It's a string"
end

===メソッドを実装することで、独自のマッチクラスを作成することができます:

class Empty
  def self.===(object)
    !object or "" == object
  end
end

case ""
when Empty
  puts "name was empty"
else
  puts "name is not empty"
end

case文は、一致する値を指定せずに使用できます。

case
when ENV['A'] == 'Y'
  puts 'A'
when ENV['B'] == 'Y'
  puts 'B'
else
  puts 'Neither A nor B'
end

caseステートメントには値があるので、メソッドの引数または代入として使用できます。

description = case 16
              when 13..19 then "teenager"
              else ""
              end

ブレーク、次、およびやり直しによるループ制御

Rubyブロックの実行フローは、 breaknextredoステートメントで制御できます。

break

breakステートメントはブロックを直ちに終了します。ブロック内の残りの命令はスキップされ、反復は終了します。

actions = %w(run jump swim exit macarena)
index = 0

while index < actions.length
  action = actions[index]

  break if action == "exit"

  index += 1
  puts "Currently doing this action: #{action}"
end

# Currently doing this action: run
# Currently doing this action: jump
# Currently doing this action: swim

next

nextステートメントはすぐにブロックの先頭に戻り、次の繰り返しに進みます。ブロック内の残りの命令はスキップされます。

actions = %w(run jump swim rest macarena)
index = 0

while index < actions.length
  action = actions[index]
  index += 1

  next if action == "rest"

  puts "Currently doing this action: #{action}"
end

# Currently doing this action: run
# Currently doing this action: jump
# Currently doing this action: swim
# Currently doing this action: macarena

redo

redo文はブロックのすぐ上に戻り、同じ反復を再試行します。ブロック内の残りの命令はスキップされます。

actions = %w(run jump swim sleep macarena)
index = 0
repeat_count = 0

while index < actions.length
  action = actions[index]
  puts "Currently doing this action: #{action}"

  if action == "sleep"
    repeat_count += 1
    redo if repeat_count < 3
  end

  index += 1
end

# Currently doing this action: run
# Currently doing this action: jump
# Currently doing this action: swim
# Currently doing this action: sleep
# Currently doing this action: sleep
# Currently doing this action: sleep
# Currently doing this action: macarena

Enumerable繰り返し

ループに加えて、これらのステートメントは、 eachmapなどのEnumerable反復メソッドで動作します。

[1, 2, 3].each do |item|
  next if item.even?
  puts "Item: #{item}"
end

# Item: 1
# Item: 3

結果値をブロックする

break文とnext文の両方で、値を指定してブロック結果値として使用します。

even_value = for value in [1, 2, 3]
  break value if value.even?
end

puts "The first even value is: #{even_value}"

# The first even value is: 2

スロー、キャッチ

他の多くのプログラミング言語とは異なり、 throwキーワードとcatchキーワードはRubyの例外処理とは関係ありません。

Rubyでは、他の言語のラベルと同様にthrowしてcatchます。これらは制御フローを変更するために使用されますが、例外のような「エラー」の概念には関係しません。

catch(:out) do
  catch(:nested) do
    puts "nested"
  end

  puts "before"
  throw :out
  puts "will not be executed"
end
puts "after"
# prints "nested", "before", "after"

論理文による制御フロー

直観に反するように見えるかもしれませんが、論理演算子を使って文が実行されているかどうかを判断できます。例えば:

File.exist?(filename) or STDERR.puts "#{filename} does not exist!"

これは、ファイルが存在するかどうかを確認し、エラーメッセージがない場合にのみ表示します。 or文は、それはそれはそれは価値のかどうか真か偽であるのは間違いないだろう一度実行を停止します意味し、怠け者です。第1項が真であるとすぐに、他の項の価値をチェックする必要はありません。しかし、第1項が偽であれば、第2項をチェックしなければならない。

一般的な使い方は、デフォルト値を設定することです:

glass = glass or 'full' # Optimist! 

それはまだ設定されていない場合、 glassの値を 'フル'に設定します。より簡潔には、 orシンボリックバージョンを使用することができます:

glass ||= 'empty' # Pessimist. 

また、最初の文がfalseの場合にのみ、2番目の文を実行することもできます。

File.exist?(filename) and puts "#{filename} found!"

ここでも、 and必要な場合にのみ値に到達する第二の文を実行しますので、怠け者です。

or演算子は、 andよりも優先度が低くandます。同様に、 || &&よりも優先順位が低くなります。シンボルフォームは、ワードフォームよりも優先順位が高くなります。これは、このテクニックと割り当てをいつ組み合わせるかを知るために便利です:

a = 1 and b = 2
#=> a==1
#=> b==2
a = 1 && b = 2; puts a, b
#=> a==2
#=> b==2

Rubyスタイルガイドでは以下を推奨しています。

andorキーワードは禁止されています。読みやすさを最小限にすることは、微妙なバグを導入する高い可能性に値するものではありません。ブール式の場合、常に&&||使用します。代わりに。フロー制御のififunless使用します。 &&||許容されるがあまり明確ではない。

開始、終了

beginブロックは、複数のステートメントをグループ化する制御構造です。

begin
  a = 7
  b = 6
  a * b
end

beginブロックはブロック内の最後のステートメントの値を返します。次の例は、 3を返します。

begin
  1
  2
  3
end

beginブロックは、結果を返すために複数のステートメントが必要な場合がある||=演算子を使用した条件付き代入に便利です。

circumference ||=
  begin
    radius = 7
    tau = Math::PI * 2
    tau * radius
  end

また、 rescueensurewhileifunlessなどの他のブロック構造と組み合わせて、プログラムフローをより詳細に制御することもできます。

Beginブロックは{ ... }do ... endようなコードブロックではありません。関数に渡すことはできません。

return対next:ブロック内の非ローカル戻り

この壊れたスニペットを考えてみましょう:

def foo
  bar = [1, 2, 3, 4].map do |x|
    return 0 if x.even?
    x
  end
  puts 'baz'
  bar
end
foo # => 0

mapのブロック結果の配列の値をreturnことが期待されるかもしれません。したがって、 fooの戻り値は[1, 0, 3, 0] foo [1, 0, 3, 0]ます。代わりに、 returnはメソッドfooから値を返しますbazは印刷されていないことに注意してください。これは実行が決してその行に達していないことを意味します

next価値があるのはトリックです。これはブロックレベルのreturnとして機能します。

def foo
  bar = [1, 2, 3, 4].map do |x|
    next 0 if x.even?
    x
  end
  puts 'baz'
  bar
end
foo # baz
    # => [1, 0, 3, 0]

ない場合にはreturn 、ブロックによって返された値は、その最後の式の値です。

等号/条件付き代入演算子(|| =)

Rubyには、変数がnilまたはfalseいずれかに評価される場合にのみ、変数に代入できるようにする等号演算子があります。

 ||= # this is the operator that achieves this. 

この演算子は、二重パイプがorを表し、そして等号は値の代入を表します。あなたはそれが次のようなものであると考えるかもしれません:

 x = x || y

この上の例は正しくありません。 or-equals演算子は、実際にはこれを表します。

 x || x = y

xnilまたはfalse評価された場合、 xyの値が割り当てられ、それ以外の場合は変更されません。

これは、等号演算子の実際の使用例です。ユーザーに電子メールを送信する予定のコードの一部があるとします。これまで何の理由であれ、このユーザーの電子メールがない場合はどうしますか?あなたは次のようなものを書くかもしれません:

 if user_email.nil?
    user_email = "[email protected]"
 end

or-equals演算子を使用して、このコード全体をカットして、きれいで明確な制御と機能を提供します。

 user_email ||= "[email protected]"

falseが有効な値である場合は、 falseてそれを上書きしないように注意する必要があります。

has_been_run = false
has_been_run ||= true
#=> true

has_been_run = false
has_been_run = true if has_been_run.nil?
#=> false

三項演算子

Rubyには三項演算子( ?: :)があり、条件が真理として評価される場合に基づいて2つの値の1つを返します。

conditional ? value_if_truthy : value_if_falsy

value = true
value ? "true" : "false"
#=> "true"

value = false
value ? "true" : "false"
#=> "false"

三つ目が優先されるが、 if a then b else c end書き込むことと同じである

例:

puts (if 1 then 2 else 3 end) # => 2

puts 1 ? 2 : 3                # => 2

x = if 1 then 2 else 3 end
puts x                        # => 2

フリップフロップ演算子

フリップフロップ演算子..は、条件文の2つの条件の間で使用され..

(1..5).select do |e|
  e if (e == 2) .. (e == 4)
end
# => [2, 3, 4]

条件は、最初の部分がtrueなるまで false評価されtrue 。次に、2番目の部分がtrueなるまで trueに評価されtrue 。その後、再びfalseに切り替わります。

この例は、何が選択されているかを示しています。

[1, 2, 2, 3, 4, 4, 5].select do |e|
  e if (e == 2) .. (e == 4)
end
# => [2, 2, 3, 4]

フリップフロップ演算子のみ(含む内部IFS動作しunless )と三項演算子を。それ以外の場合は範囲​​演算子と見なされます。

(1..5).select do |e|
  (e == 2) .. (e == 4)
end
# => ArgumentError: bad value for range

それはfalseからtrue 、そして複数回後方に切り替えることができtrue

((1..5).to_a * 2).select do |e|
  e if (e == 2) .. (e == 4)
end
# => [2, 3, 4, 2, 3, 4] 


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow