Suche…


Wenn, sonst, sonst und Ende

Ruby bietet die erwarteten if und else Ausdrücke für die Verzweigungslogik, die mit dem Schlüsselwort end beendet werden:

# 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

if Anweisungen in Ruby Ausdrücke sind, die einen Wert auswerten, und das Ergebnis einer Variablen zugewiesen werden kann:

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

Ruby bietet auch ternäre Operatoren im C-Stil ( siehe Details ), die folgendermaßen ausgedrückt werden können:

some_statement ? if_true : if_false  

Dies bedeutet, dass das obige Beispiel mit if-else auch als geschrieben werden kann

status = age < 18 ? :minor : :adult

Darüber hinaus bietet Ruby das Schlüsselwort elsif das einen Ausdruck akzeptiert, um zusätzliche Verzweigungslogik zu elsif :

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

Wenn keine der Bedingungen in einer if / elsif Kette wahr ist und keine else Klausel vorhanden ist, wird der Ausdruck zu null ausgewertet. Dies kann in der String-Interpolation nützlich sein, da nil.to_s der leere String ist:

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

Wahrheits- und Fälschungswerte

In Ruby gibt es genau zwei Werte, die als "falsch" angesehen werden und beim Test als Bedingung für einen if Ausdruck false zurückgeben. Sie sind:

  • nil
  • boolean false

Alle anderen Werte werden als "wahr" angesehen, einschließlich:

  • 0 - numerische Null (Ganzzahl oder anders)
  • "" - Leere Zeichenfolgen
  • "\n" - Zeichenfolgen, die nur Leerzeichen enthalten
  • [] - Leere Arrays
  • {} - Leere Hashes

Nehmen Sie zum Beispiel den folgenden Code:

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", {})

Wird ausgegeben:

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

während, bis

Eine while Schleife führt den Block aus, während die angegebene Bedingung erfüllt ist:

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

Ein until Schleife führt den Block , während die bedingten falsch ist :

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

Inline wenn / wenn nicht

Ein übliches Muster ist ein Inline - oder nachlauf zu verwenden, if oder unless :

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

Dies ist als bedingter Modifikator bekannt und bietet eine praktische Möglichkeit, einfachen Guard-Code und frühe Rückkehr hinzuzufügen:

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

  File.write(filename, data)
end

Es ist nicht möglich, diesen Modifizierern eine else Klausel hinzuzufügen. Auch ist es in der Regel nicht empfohlen , bedingte Modifikatoren innerhalb der Hauptlogik zu verwenden - Für komplexen Code sollte man verwenden normale if , elsif , else statt.

es sei denn

Eine häufige Aussage ist if !(some condition) . Ruby bietet die Alternative der unless Anweisung an.

Die Struktur entspricht genau einer if Anweisung, es sei denn, die Bedingung ist negativ. Auch die , unless Anweisung nicht unterstützt elsif , aber es unterstützt else :

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

Fallerklärung

Ruby verwendet das case Schlüsselwort für switch-Anweisungen.

Wie in den Ruby Docs :

Case-Anweisungen bestehen aus einer optionalen Bedingung, die sich in der Position eines Arguments von case zu case , und null oder mehr when Klauseln. Die erste when Klausel, die mit der Bedingung übereinstimmt (oder der Booleschen Wahrheit entspricht, wenn die Bedingung null ist) "gewinnt", und ihre Code-Zeilengruppe wird ausgeführt. Der Wert der case-Anweisung ist der Wert der erfolgreichen when Klausel oder nil wenn keine solche Klausel vorhanden ist.

Eine case-Anweisung kann mit einer else Klausel enden. Jedes Mal, when eine Anweisung mehrere durch Kommas getrennte Kandidatenwerte enthalten kann.

Beispiel:

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

Kürzere Version:

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

Der Wert der case Klausel wird mit jeder when Klausel mit der Methode === (nicht == ) abgeglichen. Daher kann es mit einer Vielzahl verschiedener Objekttypen verwendet werden.

Eine case Anweisung kann mit Ranges verwendet werden :

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

Eine case Anweisung kann mit einer Regexp verwendet werden :

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

Eine case Anweisung kann mit einem Proc oder Lambda verwendet werden:

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

Eine case Anweisung kann mit Klassen verwendet werden :

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

Durch die Implementierung der Methode === können Sie eigene Match-Klassen erstellen:

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

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

Eine case Anweisung kann ohne einen entsprechenden Wert verwendet werden:

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

Eine case Anweisung hat einen Wert, sodass Sie sie als Methodenargument oder in einer Zuweisung verwenden können:

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

Schleifensteuerung mit Pause, Weiter und Wiederholen

Der Ausführungsablauf eines Ruby-Blocks kann mit den Anweisungen break , next und redo gesteuert werden.

break

Die break Anweisung beendet den Block sofort. Alle verbleibenden Anweisungen im Block werden übersprungen und die Iteration wird beendet:

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

Die next Anweisung kehrt sofort zum Anfang des Blocks zurück und fährt mit der nächsten Iteration fort. Alle verbleibenden Anweisungen im Block werden übersprungen:

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

Die redo kehrt sofort zum Anfang des Blocks zurück und wiederholt dieselbe Iteration. Alle verbleibenden Anweisungen im Block werden übersprungen:

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 Iteration

Neben Schleifen arbeiten diese Aussagen mit Enumerable Iterationsverfahren, wie each und map :

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

# Item: 1
# Item: 3

Ergebniswerte blockieren

In den Anweisungen break und next kann ein Wert angegeben werden, der als Blockergebniswert verwendet wird:

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

werfen, fangen

Im Gegensatz zu vielen anderen Programmiersprachen beziehen sich die Schlüsselwörter throw und catch nicht auf die Ausnahmebehandlung in Ruby.

In Ruby wirken throw und catch ein bisschen wie Etiketten in anderen Sprachen. Sie werden verwendet, um den Steuerfluss zu ändern, beziehen sich jedoch nicht auf ein "Fehler" -Konzept wie Ausnahmen sind.

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"

Kontrollfluss mit logischen Anweisungen

Auch wenn dies nicht intuitiv erscheinen mag, können Sie mit logischen Operatoren feststellen, ob eine Anweisung ausgeführt wird oder nicht. Zum Beispiel:

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

Dadurch wird geprüft, ob die Datei vorhanden ist, und die Fehlernachricht wird nur gedruckt, wenn dies nicht der Fall ist. Die or -Anweisung ist faul, was bedeutet, dass sie nicht mehr ausgeführt wird, wenn sie sicher ist, ob der Wert wahr oder falsch ist. Sobald festgestellt wird, dass der erste Begriff wahr ist, muss der Wert des anderen Begriffs nicht überprüft werden. Wenn der erste Begriff jedoch falsch ist, muss er den zweiten Begriff überprüfen.

Häufig wird ein Standardwert festgelegt:

glass = glass or 'full' # Optimist! 

Dadurch wird der Wert von glass auf 'voll' gesetzt, wenn es nicht bereits eingestellt ist. Genauer gesagt können Sie die symbolische Version von or :

glass ||= 'empty' # Pessimist. 

Es ist auch möglich, die zweite Anweisung nur auszuführen, wenn die erste Anweisung falsch ist:

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

Wiederum and ist faul, so dass sie die zweite Anweisung nur ausführt, wenn dies erforderlich ist, um einen Wert zu erhalten.

Der Operator or hat eine niedrigere Priorität als and . Ebenso || hat eine niedrigere Priorität als && . Die Symbolformen haben eine höhere Priorität als die Wortformen. Dies ist praktisch, wenn Sie wissen möchten, wann Sie diese Technik mit Zuweisung kombinieren möchten:

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

Beachten Sie, dass der Ruby Style Guide Folgendes empfiehlt :

Die Schlüsselwörter and und or sind verboten. Die minimale zusätzliche Lesbarkeit lohnt sich einfach nicht für die hohe Wahrscheinlichkeit, subtile Fehler einzuführen. Verwenden Sie für boolesche Ausdrücke immer && und || stattdessen. Verwenden Sie für die Flusskontrolle if und unless ; && und || sind auch akzeptabel, aber weniger klar.

beginnen, ende

Der begin Block ist eine Kontrollstruktur, die mehrere Anweisungen zusammenfasst.

begin
  a = 7
  b = 6
  a * b
end

Ein begin Block gibt den Wert der letzten Anweisung im Block zurück. Das folgende Beispiel gibt 3 .

begin
  1
  2
  3
end

Der begin Block ist nützlich für die bedingte Zuweisung mit dem Operator ||= , wo möglicherweise mehrere Anweisungen erforderlich sind, um ein Ergebnis zurückzugeben.

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

Es kann auch mit anderen Blockstrukturen wie kombiniert wird rescue , ensure , while , if , unless , etc größere Strömungskontrolle des Programms zur Verfügung zu stellen.

Begin sind keine Codeblöcke wie { ... } oder do ... end ; Sie können nicht an Funktionen übergeben werden.

return vs. next: nichtlokale Rückkehr in einem Block

Betrachten Sie dieses abgebrochene Snippet:

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

Man könnte erwarten, dass return einen Wert für das Blockergebnis der map ergibt. Der Rückgabewert von foo wäre also [1, 0, 3, 0] . Stattdessen gibt return einen Wert aus der Methode foo . Beachten Sie, dass baz nicht gedruckt wird, was bedeutet, dass die Ausführung diese Zeile nie erreicht hat.

next mit einem Wert macht den Trick. Es wirkt als return Blockebene.

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]

Ohne return ist der vom Block zurückgegebene Wert der Wert des letzten Ausdrucks.

Oder-Gleich / Bedingter Zuweisungsoperator (|| =)

Ruby verfügt über einen or-equals-Operator, der die Zuweisung eines Werts zu einer Variablen ermöglicht, und zwar nur dann, wenn diese Variable entweder nil oder false .

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

dieser Operator, wobei die doppelten Pipes oder oder das Gleichheitszeichen die Zuweisung eines Wertes darstellen. Sie denken vielleicht, dass es so etwas darstellt:

 x = x || y

Dieses obige Beispiel ist nicht korrekt. Der or-equals-Operator stellt dies tatsächlich dar:

 x || x = y

Wenn x nil oder false ergibt, wird x den Wert von y zugewiesen und ansonsten unverändert gelassen.

Hier ist ein praktischer Anwendungsfall des Operators or-equals. Stellen Sie sich vor, Sie haben einen Teil Ihres Codes, von dem erwartet wird, dass er eine E-Mail an einen Benutzer sendet. Was tun Sie, wenn aus irgendeinem Grund keine E-Mail für diesen Benutzer vorliegt? Sie könnten so etwas schreiben:

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

Mit dem Operator or-equals können wir den gesamten Code-Code ausschneiden und so eine klare, klare Kontrolle und Funktionalität bieten.

 user_email ||= "[email protected]"

Wenn false ein gültiger Wert ist, muss darauf geachtet werden, dass der Wert nicht versehentlich überschrieben wird:

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

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

Ternärer Operator

Ruby hat einen ternären Operator ( ?: :), Der einen von zwei Werten zurückgibt, die darauf basieren, ob eine Bedingung als wahr bewertet wird:

conditional ? value_if_truthy : value_if_falsy

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

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

es ist dasselbe wie das Schreiben, if a then b else c end , obwohl das ternäre bevorzugt wird

Beispiele:

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

Flip-Flop-Operator

Der Flip-Flop-Operator .. wird zwischen zwei Bedingungen in einer Bedingungsanweisung verwendet:

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

Die Bedingung wird als false ausgewertet, bis der erste Teil true . Dann wird es als true bewertet, bis der zweite Teil true . Danach wechselt es wieder auf false .

Dieses Beispiel zeigt, was ausgewählt wird:

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

Der Flip-Flop-Operator funktioniert nur innerhalb von ifs (einschließlich, unless ) und ternärem Operator. Andernfalls wird es als Bereichsoperator betrachtet.

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

Sie kann mehrmals von false nach true und zurück wechseln:

((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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow