Ricerca…


se, elsif, else e end

Ruby offre le espressioni if e else previste per la logica di branching, terminate dalla parola chiave end :

# 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, le istruzioni if sono espressioni che valutano un valore e il risultato può essere assegnato a una variabile:

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

Ruby offre anche operatori ternari in stile C ( vedi qui per i dettagli ) che possono essere espressi come:

some_statement ? if_true : if_false  

Ciò significa che l'esempio precedente che usa if-else può anche essere scritto come

status = age < 18 ? :minor : :adult

Inoltre, Ruby offre la parola chiave elsif che accetta un'espressione per abilitare la logica di ramificazione aggiuntiva:

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

Se nessuna delle condizioni in un if / elsif catena sono vere, e non c'è nessun else la clausola, quindi l'espressione restituisce a zero. Questo può essere utile all'interno dell'interpolazione delle stringhe, poiché nil.to_s è la stringa vuota:

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

Valori di verità e Falsy

In Ruby, ci sono esattamente due valori che sono considerati "falsi" e restituiscono false quando testati come condizione per un'espressione if . Loro sono:

  • nil
  • booleano false

Tutti gli altri valori sono considerati "veritieri", tra cui:

  • 0 - zero numerico (intero o altro)
  • "" - Stringhe vuote
  • "\n" - Stringhe contenenti solo spazi bianchi
  • [] - Array vuoti
  • {} - hash vuoti

Prendi, ad esempio, il seguente codice:

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

Produrrà:

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

mentre, fino a

Un ciclo while esegue il blocco mentre viene soddisfatta la condizione data:

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

Un ciclo until esegue il blocco mentre il condizionale è falso:

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

In linea se / a meno

Un modello comune consiste nell'utilizzare un inline o trailing, if o unless :

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

Questo è noto come modificatore condizionale ed è un modo pratico per aggiungere codice di protezione semplice e ritorni anticipati:

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

  File.write(filename, data)
end

Non è possibile aggiungere una clausola else a questi modificatori. Inoltre, in genere non è raccomandato l'uso di modificatori condizionali all'interno della logica principale - Per i codici complessi si dovrebbe usare normalmente if , elsif , else .

salvo che

Una dichiarazione comune è if !(some condition) . Ruby offre l'alternativa della dichiarazione a unless che.

La struttura è esattamente la stessa di un'istruzione if , eccetto che la condizione è negativa. Inoltre, l'istruzione a unless che non supporta elsif , ma supporta else :

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

Caso clinico

Ruby usa la parola chiave case per le istruzioni switch.

Come da Ruby Docs :

Le affermazioni di caso sono costituite da una condizione facoltativa, che è nella posizione di un argomento a case e da zero o più clausole when . La prima clausola when corrisponde alla condizione (o per valutare la verità booleana, se la condizione è nulla) "vince" e la sua stanza di codice viene eseguita. Il valore dell'istruzione case è il valore della clausola when successful, o nil se non esiste tale clausola.

Una dichiarazione di un caso può terminare con else clausola. Ciascuno when un'istruzione può avere più valori candidati, separati da virgole.

Esempio:

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

Versione più breve:

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

Il valore della clausola case viene confrontato con ciascuna clausola when utilizzando il metodo === (non == ). Pertanto può essere utilizzato con una varietà di diversi tipi di oggetti.

È possibile utilizzare un'istruzione case con gli intervalli :

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

Una dichiarazione di un case può essere utilizzata con un Regexp :

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

Una dichiarazione del case può essere utilizzata con un Proc o lambda:

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

È possibile utilizzare un'istruzione case con Classi :

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

Implementando il metodo === puoi creare le tue classi di corrispondenza:

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

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

È possibile utilizzare un'istruzione case senza un valore con cui confrontare:

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

Un'istruzione case ha un valore, quindi puoi usarla come argomento metodo o in un compito:

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

Controllo del ciclo con interruzione, successivo e ripetizione

Il flusso di esecuzione di un blocco Ruby può essere controllato con le istruzioni break , next e redo .

break

L'istruzione break uscirà immediatamente dal blocco. Qualsiasi istruzione rimanente nel blocco verrà saltata e l'iterazione terminerà:

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

La next istruzione tornerà immediatamente all'inizio del blocco e procederà con la successiva iterazione. Qualsiasi istruzione rimanente nel blocco verrà saltata:

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

L'istruzione redo ritorna immediatamente all'inizio del blocco e riprova la stessa iterazione. Qualsiasi istruzione rimanente nel blocco verrà saltata:

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 iterativa

Oltre ai cicli, queste istruzioni funzionano con i metodi di iterazione Enumerable, come each e map :

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

# Item: 1
# Item: 3

Blocca i valori dei risultati

In entrambe le istruzioni break e next , può essere fornito un valore, che verrà utilizzato come valore del risultato del blocco:

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

buttare, prendere

A differenza di molti altri linguaggi di programmazione, le parole chiave throw and catch non sono correlate alla gestione delle eccezioni in Ruby.

In Ruby, throw e catch atti un po 'come etichette in altre lingue. Sono usati per cambiare il flusso di controllo, ma non sono correlati a un concetto di "errore" come sono le eccezioni.

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"

Controllo del flusso con istruzioni logiche

Anche se può sembrare controintuitivo, è possibile utilizzare gli operatori logici per determinare se viene eseguita o meno un'istruzione. Per esempio:

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

Questo controllerà se il file esiste e stamperà il messaggio di errore solo se non lo è. L'istruzione or è pigro, il che significa che smetterà di essere eseguito una volta che è sicuro se il suo valore sia vero o falso. Non appena viene scoperto che il primo termine è vero, non è necessario verificare il valore dell'altro termine. Ma se il primo termine è falso, deve controllare il secondo termine.

Un uso comune è impostare un valore predefinito:

glass = glass or 'full' # Optimist! 

Questo imposta il valore del glass su "pieno" se non è già impostato. Più concisamente, è possibile utilizzare la versione simbolica di or :

glass ||= 'empty' # Pessimist. 

È anche possibile eseguire la seconda istruzione solo se la prima è falsa:

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

Di nuovo, and è pigro, quindi eseguirà la seconda istruzione solo se necessario per arrivare a un valore.

L'operatore or ha una precedenza inferiore rispetto a and . Allo stesso modo, || ha precedenza più bassa di && . Le forme simbolo hanno una precedenza superiore rispetto alle forme di parole. Questo è utile sapere quando si desidera mescolare questa tecnica con l'assegnazione:

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

Si noti che la Guida allo stile di Ruby consiglia :

E and or parole chiave sono bannati. La minima leggibilità aggiunta non merita l'alta probabilità di introdurre bug sottili. Per le espressioni booleane, usa sempre && e || anziché. Per il controllo del flusso, utilizzare if e a unless ; && e || sono anche accettabili ma meno chiari.

inizio, fine

L' begin blocco è una struttura di controllo che raggruppa più istruzioni.

begin
  a = 7
  b = 6
  a * b
end

A begin blocco restituirà il valore dell'ultima istruzione nel blocco. Il seguente esempio restituirà 3 .

begin
  1
  2
  3
end

L' begin blocco è utile per l'assegnazione condizionale usando l' ||= gestore, nella quale possono essere necessarie più istruzioni per restituire un risultato.

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

Può anche essere combinato con altre strutture di blocco come il rescue , ensure , while , if , unless , ecc. Per fornire un maggiore controllo del flusso del programma.

Begin blocchi Begin non sono blocchi di codice, come { ... } o do ... end ; non possono essere passati alle funzioni.

return vs. next: ritorno non locale in un blocco

Considera questo frammento spezzato :

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

Ci si potrebbe aspettare che il return restituisca un valore per la matrice di risultati di blocco della map . Quindi il valore di ritorno di foo sarebbe [1, 0, 3, 0] . Invece, return restituisce un valore dal metodo foo . Si noti che baz non viene stampato, il che significa che l'esecuzione non ha mai raggiunto quella linea.

next con un valore fa il trucco. Funziona come un return livello di blocco.

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]

In assenza di un return , il valore restituito dal blocco è il valore della sua ultima espressione.

Operatore di assegnazione Or-Ugual / Conditional (|| =)

Ruby ha un operatore or-equal che consente di assegnare un valore a una variabile se e solo se tale variabile valuta o nil o false .

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

questo operatore con i doppi tubi che rappresentano o e il segno di uguale che rappresenta l'assegnazione di un valore. Potresti pensare che rappresenti qualcosa del genere:

 x = x || y

questo esempio sopra non è corretto. L'operatore or-equal rappresenta effettivamente questo:

 x || x = y

Se x restituisce un valore nil o false x viene assegnato il valore di y e lasciato invariato altrimenti.

Ecco un caso d'uso pratico dell'operatore or-equal. Immagina di avere una parte del codice che ci si aspetta che invii un messaggio di posta elettronica a un utente. Cosa fai se per qualsiasi motivo non ci sono e-mail per questo utente. Potresti scrivere qualcosa come questo:

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

Usando l'operatore or-equal possiamo tagliare l'intera porzione di codice, fornendo un controllo e una funzionalità chiari e chiari.

 user_email ||= "[email protected]"

Nei casi in cui il false è un valore valido, è necessario fare attenzione a non ignorarlo accidentalmente:

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

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

Operatore ternario

Ruby ha un operatore ternario ( ?: :), Che restituisce uno dei due valori in base a se una condizione viene valutata come verità:

conditional ? value_if_truthy : value_if_falsy

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

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

è lo stesso che scrivere if a then b else c end , anche se il ternario è preferito

Esempi:

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

Operatore Flip-Flop

L'operatore flip flop .. viene utilizzato tra due condizioni in un'istruzione condizionale:

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

La condizione diventa false fino a quando la prima parte diventa true . Quindi valuta true finché la seconda parte diventa true . Dopodiché passa nuovamente a false .

Questo esempio illustra cosa viene selezionato:

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

L'operatore flip-flop funziona solo all'interno di ifs (incluso a unless ) e dell'operatore ternario. Altrimenti viene considerato come l'operatore di intervallo.

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

Può passare da false a true e viceversa più volte:

((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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow