Zoeken…


als, elsif, anders en einde

Ruby biedt de verwachte if en else uitdrukkingen voor vertakkende logica, beëindigd door het end trefwoord:

# 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

In Ruby, if statements uitdrukkingen zijn die evalueren naar een waarde en het resultaat kan worden toegewezen aan een variabele:

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

Ruby biedt ook ternaire operatoren in C-stijl ( zie hier voor details ) die kunnen worden uitgedrukt als:

some_statement ? if_true : if_false  

Dit betekent dat het bovenstaande voorbeeld met if-else ook kan worden geschreven als

status = age < 18 ? :minor : :adult

Bovendien biedt Ruby het sleutelwoord elsif dat een expressie accepteert om aanvullende vertakkingslogica mogelijk te maken:

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

Als geen van de omstandigheden in een if / elsif keten waar zijn, en er is geen else artikel, dan is de expressie de waarde nihil. Dit kan handig zijn binnen stringinterpolatie, omdat nil.to_s de lege string is:

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

Waarheid en valse waarden

In Ruby zijn er precies twee waarden die als "vals" worden beschouwd en die onwaar zullen retourneren wanneer ze worden getest als voorwaarde voor een if expressie. Zij zijn:

  • nil
  • boolean false

Alle andere waarden worden als "waarheidsgetrouw" beschouwd, waaronder:

  • 0 - numerieke nul (geheel of anders)
  • "" - Lege tekenreeksen
  • "\n" - Tekenreeksen die alleen witruimte bevatten
  • [] - Lege arrays
  • {} - Lege hashes

Neem bijvoorbeeld de volgende 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", {})

Zal uitvoeren:

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

terwijl, tot

Een while lus voert het blok uit terwijl aan de gegeven voorwaarde is voldaan:

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

Een until lus voert het blok terwijl de voorwaardelijke vals:

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

Inline indien / tenzij

Een gebruikelijk patroon is het gebruik van een inline, of een volgnummer, if of unless :

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

Dit staat bekend als een voorwaardelijke modificator en is een handige manier om eenvoudige bewakingscode en vroegtijdig rendement toe te voegen:

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

  File.write(filename, data)
end

Het is niet mogelijk om een else component aan deze modificaties toe te voegen. Ook is het in het algemeen niet aan te raden om voorwaardelijke modifiers gebruiken in het hoofdgebouw logica - Voor complexe code moet men gebruik maken van de normale if , elsif , else plaats.

tenzij

Een veel voorkomende verklaring is if !(some condition) . Ruby biedt het alternatief van de unless verklaring.

De structuur is exact hetzelfde als een if instructie, behalve dat de voorwaarde negatief is. Ook ondersteunt de unless instructie geen elsif , maar wel else :

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

Case statement

Ruby gebruikt het sleutelwoord case voor schakelinstructies.

Volgens de Ruby Docs :

Case-uitspraken bestaan uit een optionele voorwaarde, die in de positie van argument tot case , en nul of meer when clausules. De eerste when clausule om de conditie te passen (of te evalueren in Boolean waarheid, als de voorwaarde null) “wint”, en de code strofe wordt uitgevoerd. De waarde van de zaak uitspraak is de waarde van de succesvolle when clausule, of nil als er geen dergelijke clausule.

Een case-statement kan eindigen met een else clausule. Elke keer when een statement meerdere kandidaatwaarden kan hebben, gescheiden door komma's.

Voorbeeld:

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

Kortere versie:

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

De waarde van de case clausule komt overeen met elke clausule when clausule wordt gebruikt met de methode === (niet == ). Daarom kan het worden gebruikt met verschillende soorten objecten.

Een case statement kan worden gebruikt met Ranges :

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

Een case statement kan worden gebruikt met een Regexp :

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

Een case statement kan worden gebruikt met een Proc of lambda:

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

Een case -instructie kan worden gebruikt met Classes :

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

Door de === methode te implementeren, kunt u uw eigen wedstrijdklassen maken:

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

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

Een case statement kan worden gebruikt zonder een waarde die overeenkomt met:

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

Een case instructie heeft een waarde, dus u kunt deze gebruiken als methode-argument of in een opdracht:

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

Lusbesturing met pauze, volgende en opnieuw uitvoeren

De stroom van uitvoering van een Ruby-blok kan worden geregeld met de instructies break , next en redo .

break

De break verlaat het blok onmiddellijk. Alle resterende instructies in het blok worden overgeslagen en de iteratie wordt beëindigd:

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

De next instructie keert onmiddellijk terug naar de bovenkant van het blok en gaat door met de volgende iteratie. Alle resterende instructies in het blok worden overgeslagen:

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

De instructie redo keert onmiddellijk terug naar de bovenkant van het blok en probeert dezelfde iteratie opnieuw. Alle resterende instructies in het blok worden overgeslagen:

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 iteratie

Naast lussen werken deze instructies met Enumerable iteratiemethoden, zoals each en map :

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

# Item: 1
# Item: 3

Resultaatwaarden blokkeren

In zowel de break als de next instructies kan een waarde worden opgegeven en deze wordt gebruikt als een blokresultaatwaarde:

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

gooien vangen

In tegenstelling tot veel andere programmeertalen, zijn de trefwoorden throw en catch niet gerelateerd aan het afhandelen van uitzonderingen in Ruby.

In Ruby gedragen throw en catch een beetje zoals labels in andere talen. Ze worden gebruikt om de besturingsstroom te wijzigen, maar zijn niet gerelateerd aan een concept van "fout" zoals uitzonderingen.

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"

Besturingsstroom met logische instructies

Hoewel het contra-intuïtief lijkt, kunt u logische operatoren gebruiken om te bepalen of een instructie al dan niet wordt uitgevoerd. Bijvoorbeeld:

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

Hiermee wordt gecontroleerd of het bestand bestaat en wordt alleen het foutbericht afgedrukt als dit niet het geval is. De instructie or is lui, wat betekent dat deze stopt met uitvoeren zodra het zeker is of de waarde waar of onwaar is. Zodra de eerste term waar blijkt te zijn, hoeft de waarde van de andere term niet te worden gecontroleerd. Maar als de eerste term vals is, moet deze de tweede term controleren.

Een algemeen gebruik is om een standaardwaarde in te stellen:

glass = glass or 'full' # Optimist! 

Dat stelt de waarde van glass op 'vol' als het nog niet is ingesteld. Korter, u kunt de symbolische versie gebruiken van or :

glass ||= 'empty' # Pessimist. 

Het is ook mogelijk om de tweede instructie alleen uit te voeren als de eerste onwaar is:

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

Nogmaals, and is lui, dus het zal alleen de tweede instructie uitvoeren als dat nodig is om tot een waarde te komen.

De operator or heeft een lagere prioriteit dan and . Evenzo || heeft een lagere prioriteit dan && . De symboolvormen hebben een hogere prioriteit dan de woordvormen. Dit is handig om te weten wanneer je deze techniek met opdracht wilt combineren:

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

Merk op dat de Ruby Style Guide aanbeveelt :

De and en or sleutelwoorden zijn verboden. De minimale toegevoegde leesbaarheid is de grote kans op het introduceren van subtiele bugs gewoon niet waard. Gebruik voor booleaanse uitdrukkingen altijd && en || in plaats daarvan. Gebruik if en unless voor stroomregeling; && en || zijn ook acceptabel, maar minder duidelijk.

begin, einde

Het begin is een besturingsstructuur die meerdere instructies groepeert.

begin
  a = 7
  b = 6
  a * b
end

Een begin retourneert de waarde van de laatste instructie in het blok. Het volgende voorbeeld retourneert 3 .

begin
  1
  2
  3
end

Het begin is handig voor voorwaardelijke toewijzing met de operator ||= waarbij meerdere instructies nodig kunnen zijn om een resultaat te retourneren.

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

Het kan ook worden gecombineerd met andere blokstructuren zoals rescue , ensure , while , if , unless , enz. Om een grotere controle over de programmastroom te bieden.

Begin zijn geen codeblokken, zoals { ... } of do ... end ; ze kunnen niet worden doorgegeven aan functies.

terugkeer versus volgende: niet-lokale terugkeer in een blok

Beschouw dit gebroken fragment:

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

Je zou verwachten dat return een waarde oplevert voor de reeks blokresultaten van de map . Dus de retourwaarde van foo zou [1, 0, 3, 0] . In plaats daarvan return return een waarde van de methode foo . Merk op dat baz niet wordt afgedrukt, wat betekent dat de uitvoering die lijn nooit heeft bereikt.

next met een waarde volstaat. Het fungeert als een return blokniveau.

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]

Bij afwezigheid van een return , is de waarde die door het blok wordt geretourneerd de waarde van zijn laatste uitdrukking.

Or-is gelijk aan / Voorwaardelijke toewijzingsoperator (|| =)

Ruby heeft een operator of is gelijk aan waarmee een waarde aan een variabele kan worden toegewezen als en alleen als die variabele nil of false .

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

deze operator met de dubbele pijpen die of vertegenwoordigen en het isgelijkteken dat een waarde toekent. Je denkt misschien dat het zoiets als dit vertegenwoordigt:

 x = x || y

dit bovenstaande voorbeeld is niet correct. De operator or-is gelijk aan dit:

 x || x = y

Als x aan nil of false , krijgt x de waarde van y en wordt anders ongewijzigd gelaten.

Hier is een praktische use-case van de operator of is gelijk aan. Stel je voor dat je een deel van je code hebt dat naar verwachting een e-mail naar een gebruiker zal verzenden. Wat doe je als er om welke reden dan ook geen e-mail is voor deze gebruiker. Je zou zoiets kunnen schrijven:

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

Met de operator of-is gelijk aan kunnen we dit hele stuk code snijden, voor een schone, duidelijke controle en functionaliteit.

 user_email ||= "[email protected]"

In gevallen waarin false een geldige waarde is, moet ervoor worden gezorgd dat deze niet per ongeluk wordt opgeheven:

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

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

Ternary operator

Ruby heeft een ternaire operator ( ?: :), Die een waarde van twee retourneert op basis van of een voorwaarde als waarheidsgetrouw wordt geëvalueerd:

conditional ? value_if_truthy : value_if_falsy

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

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

het is hetzelfde als schrijven if a then b else c end , hoewel de ternaire de voorkeur heeft

Voorbeelden:

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

De flip flop-operator .. wordt gebruikt tussen twee voorwaarden in een voorwaardelijke verklaring:

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

De voorwaarde wordt als false geëvalueerd totdat het eerste deel true . Vervolgens wordt het geëvalueerd tot true totdat het tweede deel true . Daarna schakelt het weer naar false .

Dit voorbeeld illustreert wat er wordt geselecteerd:

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

De flip-flop-operator werkt alleen binnen ifs (inclusief unless ) en ternaire operator. Anders wordt het beschouwd als de bereikoperator.

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

Het kan meerdere keren van false naar true en omgekeerd schakelen:

((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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow