Recherche…


si, elsif, sinon et fin

Ruby propose les expressions if et else attendues pour la logique de branchement, terminées par le mot clé 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

Dans Ruby, les instructions if sont des expressions dont l'évaluation donne une valeur et le résultat peut être affecté à une variable:

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

Ruby propose également des opérateurs ternaires de style C ( voir ici pour plus de détails ) pouvant être exprimés comme suit:

some_statement ? if_true : if_false  

Cela signifie que l'exemple ci-dessus utilisant if-else peut aussi être écrit comme

status = age < 18 ? :minor : :adult

En outre, Ruby propose le mot-clé elsif qui accepte une expression pour activer une logique de branchement supplémentaire:

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

Si aucune des conditions d'une chaîne if / elsif n'est vraie et qu'il n'y a pas de clause else , l'expression est nulle. Cela peut être utile dans l'interpolation de chaînes, car nil.to_s est la chaîne vide:

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

Valeurs véridiques et fausses

Dans Ruby, il y a exactement deux valeurs qui sont considérées comme "falsy", et qui retourneront false si elles sont testées comme condition pour une expression if . Elles sont:

  • nil
  • booléen false

Toutes les autres valeurs sont considérées comme "véridiques", notamment:

  • 0 - zéro numérique (entier ou autre)
  • "" - Chaînes vides
  • "\n" - Chaînes ne contenant que des espaces
  • [] - Tableaux vides
  • {} - Les hashes vides

Prenez, par exemple, le code suivant:

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

Va sortir:

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

tandis que, jusqu'à

A while la boucle exécute le bloc tandis que la condition donnée est satisfaite:

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

Un until la boucle exécute le bloc alors que le conditionnel est faux:

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

Inline si / sauf

Un schéma courant consiste à utiliser un inline ou à la fin if ou à unless :

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

Ceci est connu comme un modificateur conditionnel, et est un moyen pratique d'ajouter un code de garde simple et des retours anticipés:

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

  File.write(filename, data)
end

Il n'est pas possible d'ajouter une clause else à ces modificateurs. En outre , il est généralement recommandé de ne pas utiliser les modificateurs conditionnels dans la logique principale - Pour le code complexe on devrait utiliser la normale if , elsif , d' else à la place.

sauf si

Une déclaration commune est if !(some condition) . Ruby offre l'alternative de la déclaration unless .

La structure est exactement la même qu'une instruction if , sauf que la condition est négative. En outre, la déclaration unless ne prend pas en charge elsif , mais prend en charge else :

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

Déclaration de cas

Ruby utilise le mot-clé case pour les instructions switch.

Selon les Ruby Docs :

Les instructions de cas sont constituées d'une condition facultative, qui se trouve dans la position d'un argument par rapport à la case , et de zéro ou plusieurs when clauses. La première clause when qui correspond à la condition (ou à l'évaluation de la vérité booléenne, si la condition est nulle) «gagne» et sa strophe de code est exécutée. La valeur de l'instruction case est la valeur de la clause when , ou nil s'il n'y en a pas.

Une instruction de cas peut se terminer par une clause else . Chaque when qu'une instruction peut avoir plusieurs valeurs candidates, séparées par des virgules.

Exemple:

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

Version plus courte:

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

La valeur de la clause case correspond à chaque clause when à l'aide de la méthode === (non == ). Par conséquent, il peut être utilisé avec différents types d'objets.

Une déclaration de case peut être utilisée avec des plages :

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

Une déclaration de case peut être utilisée avec une expression rationnelle :

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

Une instruction de case peut être utilisée avec un Proc ou un lambda:

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

Une déclaration de case peut être utilisée avec les classes :

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

En implémentant la méthode === , vous pouvez créer vos propres classes de correspondance:

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

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

Une instruction de case peut être utilisée sans valeur à comparer:

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

Une instruction de case a une valeur, vous pouvez donc l'utiliser comme argument de méthode ou dans une affectation:

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

Contrôle de boucle avec break, next et redo

Le flux d'exécution d'un bloc Ruby peut être contrôlé avec les instructions break , next et redo .

break

La déclaration de break sortira immédiatement du bloc. Toutes les instructions restantes dans le bloc seront ignorées et l'itération se terminera comme suit:

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

L'instruction next retournera immédiatement en haut du bloc et poursuivra l'itération suivante. Toutes les instructions restantes dans le bloc seront ignorées:

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'instruction redo retourne immédiatement en haut du bloc et réessaie la même itération. Toutes les instructions restantes dans le bloc seront ignorées:

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

Outre les boucles, ces instructions fonctionnent avec les méthodes d'itération Enumerable, telles que each et la map :

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

# Item: 1
# Item: 3

Bloquer les valeurs de résultat

Dans les instructions break et next , une valeur peut être fournie et sera utilisée comme valeur de résultat de bloc:

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

jeter, attraper

Contrairement à de nombreux autres langages de programmation, les mots clés throw et catch ne sont pas liés à la gestion des exceptions dans Ruby.

Dans Ruby, throw et catch agissent un peu comme des étiquettes dans d'autres langues. Ils sont utilisés pour modifier le flux de contrôle, mais ne sont pas liés à un concept "d'erreur" comme les exceptions.

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"

Contrôle du flux avec des instructions logiques

Bien que cela puisse sembler contre-intuitif, vous pouvez utiliser des opérateurs logiques pour déterminer si une instruction est exécutée ou non. Par exemple:

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

Cela vérifie si le fichier existe et n'imprime le message d'erreur que si ce n'est pas le cas. L'instruction or est paresseuse, ce qui signifie qu'elle cessera de s'exécuter une fois qu'il sera certain que sa valeur est vraie ou fausse. Dès que le premier terme est trouvé vrai, il n'est pas nécessaire de vérifier la valeur de l'autre terme. Mais si le premier terme est faux, il doit vérifier le second terme.

Une utilisation courante consiste à définir une valeur par défaut:

glass = glass or 'full' # Optimist! 

Cela définit la valeur du glass à «plein» si ce n'est pas déjà fait. Plus précisément, vous pouvez utiliser la version symbolique de or :

glass ||= 'empty' # Pessimist. 

Il est également possible d'exécuter la deuxième instruction uniquement si la première est fausse:

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

Encore une fois, and est paresseux donc il n'exécutera la deuxième instruction que si nécessaire pour arriver à une valeur.

L'opérateur or a une priorité inférieure à and . De même, || a une préséance inférieure à && . Les formes de symbole ont une priorité plus élevée que les formes de mot. Ceci est pratique pour savoir quand vous voulez mélanger cette technique avec l'affectation:

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

Notez que le Guide de style Ruby recommande :

Les mots clés and et or sont interdits. La lisibilité minimale ajoutée ne vaut tout simplement pas la forte probabilité d'introduire des bogues subtils. Pour les expressions booléennes, utilisez toujours && et || au lieu. Pour le contrôle de flux, utilisez if et unless ; && et || sont également acceptables mais moins clairs.

commence, fin

Le bloc de begin est une structure de contrôle regroupant plusieurs instructions.

begin
  a = 7
  b = 6
  a * b
end

Un bloc de begin renvoie la valeur de la dernière instruction du bloc. L'exemple suivant renverra 3 .

begin
  1
  2
  3
end

Le bloc begin est utile pour l'affectation conditionnelle à l'aide de l'opérateur ||= où plusieurs instructions peuvent être nécessaires pour renvoyer un résultat.

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

Il peut également être combiné avec d'autres structures de bloc telles que le rescue , ensure , tant while , if , unless , etc. pour fournir un meilleur contrôle du déroulement du programme.

Begin blocs de do ... end ne sont pas des blocs de code, comme { ... } ou do ... end ; ils ne peuvent pas être transmis aux fonctions.

retour vs suivant: retour non local dans un bloc

Considérez cet extrait cassé :

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

On pourrait s'attendre à ce que le return donne une valeur pour le tableau de résultats de bloc de map . Donc, la valeur de retour de foo serait [1, 0, 3, 0] . Au lieu de cela, return renvoie une valeur de la méthode foo . Notez que baz n'est pas imprimé, ce qui signifie que l'exécution n'a jamais atteint cette ligne.

next avec une valeur fait le tour. Il agit comme un return niveau du bloc.

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]

En l'absence de return , la valeur renvoyée par le bloc est la valeur de sa dernière expression.

Opérateur d'attribution Or-Equals / Conditional (|| =)

Ruby possède un opérateur or-equals qui permet d'attribuer une valeur à une variable si et seulement si cette variable est nil ou false .

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

cet opérateur avec les doubles tuyaux représentant ou et le signe égal représentant l'attribution d'une valeur. Vous pensez peut-être que cela représente quelque chose comme ceci:

 x = x || y

Cet exemple ci-dessus n'est pas correct. L'opérateur or-equals représente en fait ceci:

 x || x = y

Si x évalué à nil ou à false x se voit attribuer la valeur de y et reste inchangé dans le cas contraire.

Voici un cas d'utilisation pratique de l'opérateur ou-equals. Imaginez que vous ayez une partie de votre code qui devrait envoyer un courrier électronique à un utilisateur. Que faites-vous si pour quelle raison il n'y a pas de courrier électronique pour cet utilisateur? Vous pourriez écrire quelque chose comme ceci:

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

En utilisant l'opérateur ou-equals, nous pouvons couper tout ce morceau de code, fournissant un contrôle et des fonctionnalités propres et clairs.

 user_email ||= "[email protected]"

Dans les cas où false est une valeur valide, il faut veiller à ne pas la remplacer accidentellement:

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

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

Opérateur ternaire

Ruby a un opérateur ternaire ( ?: :), Qui renvoie une valeur sur deux si une condition est évaluée comme vraie:

conditional ? value_if_truthy : value_if_falsy

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

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

c'est la même chose qu'écrire if a then b else c end , bien que le ternaire soit préféré

Exemples:

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

Opérateur Flip-Flop

L'opérateur flip flop .. est utilisé entre deux conditions dans une instruction conditionnelle:

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

La condition est false jusqu'à ce que la première partie devienne true . Ensuite , il évalue à true jusqu'à ce que la seconde partie est true . Après cela, il redevient false .

Cet exemple illustre ce qui est sélectionné:

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

L'opérateur flip-flop ne fonctionne que dans l'opérateur ifs (y compris unless ) et l'opérateur ternaire. Sinon, il est considéré comme l'opérateur de la gamme.

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

Il peut passer de false à true et inversement plusieurs fois:

((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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow