Programmation Ruby/Contrôle
Méthodes logiques.
Une expression booléenne est toute expression qui renvoie après évaluation vrai (codice_1) ou faux (codice_2).
Une valeur booléenne peut être de type booléen (codice_1 ou codice_2)
Attention: 
Il s'agit ici d'une autre des caractéristiques des langages 'tout objet' ou même les nombres sont des objets.
Tout objet est true.
Une autre caractéristique de Ruby et de tous les langages "tout objet", est que les "opérateurs", décrit ci-dessous, comme on les appelle dans les langages orientés objet ou procéduraux, sont en réalités des méthodes d'instance. En règles générale, le développeur doit implémenter lui même ses méthodes. Néanmoins certaines d'entre, dont les equivalents d'"opérateurs", sont pré-définies dans la classe codice_8, mère de toutes les autres classes, ou encore dans un module. Nous reviendrons sur ces concepts dans le chapitre traitant de la programmation objet.
Les exemples, ici, utilisent des objets "standards" pour un souci de clarté, ils peuvent être remplacés par des expressions placées entre parenthèses.
Ainsi :
 42 == 42 => true
équivaut à
 (40 + 2) == (21 * 2) => true
defined?
codice_9 permet de vérifier l'existence d'une variable, l'opérateur renvoie codice_10 si la variable n'existe pas, sinon renvoi une description :
 defined? 42 => "expression"
 defined? toto => nil
 defined? 42.times => "method"
 defined? $_ => "global-variable"
eql?
codice_11 teste si 2 variables ou valeurs sont égales et du même type, renvoi codice_1 si c'est le cas, sinon codice_2.
 42.eql?(42) => true
 42.eql?(18) => false # Valeurs différentes
 42.eql?(42.0) => false # Types différents, en effet 42 est un entier, 42.0 un flottant
equal?
codice_14 renvoie codice_1 si les deux objets comparés sont en réalité un même objet (même id), sinon renvoie codice_2.
 a = "mon objet"
 b = a
 a.equal?(a) => true
 a.equal?(b) => true
 c = "mon objet"
 a.equal?(c) => false
 42.equal?(42) => true
 "uv".equal?("uv") => false
codice_17 permet de tester l'égalité entre les valeurs de deux éléments :
 42 == 42 => true
 42 == 23 => false
 42 == "42" => false
codice_18 permet de tester l'inégalité entre les valeurs de deux éléments :
 42 != 42 => false
 42 != 23 => true
 42 != "42" => true
codice_19 sert à comparer deux variables, cette méthode n'est pas à proprement parler un opérateur booléen. En effet celle-ci renvoie codice_20, codice_21 ou codice_22 si, le premier élément est respectivement inférieur, égal ou supérieur au second, et renvoie codice_10 si les types sont différents.
 2 <=> 2 => 0
 2 <=> 3 => -1
 42 <=> 18 => 1
 42 <=> "42" => nil
 42 <=> 42.0 => 0 # contrairement à eql?, c'est la valeur qui est comparée
Pour deux valeurs numériques cet opérateur retourne donc le signe de la différence entre celles-ci.
< et <=.
codice_24 et codice_25 correspondent respectivement à "inférieur" et "inférieur ou égal à" :
 42 < 43 => true
 42 < 42 => false
 42 <= 42 => true
 "abcdef" < "abzd" => true #la comparaison entre chaînes de caractères se fait lettre à lettre
 "abzd" < "abcdef" => false 
> et >=.
codice_26 et codice_27 correspondent respectivement à "supérieur à" et "supérieur ou égal à" :
 42 > 43 => false
 42 > 42 => false
 42 >= 42 => true
 "abcdef" > "abzd" => false #la comparaison entre chaînes de caractères se fait lettre à lettre
 "abzd" > "abcdef" => true
not et !
codice_28 et codice_29 exprime la négation, l'opérateur "inverse" l'élément placé juste après, ainsi :
 not true => false
 (!false) => true
De même, on peut exprimer la négation sur une expression si celle-ci se trouve entre parenthèses :
 (!(2 < 10)) => false
 not (2 < 10) => false
and et &&.
codice_30 et codice_31 correspondent au "et logique" :
 true and false => false
 true and true => true
Dans un souci d'optimisation, Ruby teste la première expression, et si celle-ci est fausse, il ne teste pas la seconde.
or et ||.
codice_32 et codice_33 correspondent au "ou logique"
 true or false => true
 true or true => true
 false or false => false
Dans un souci d'optimisation, Ruby teste la première expression, et si celle-ci est vraie, il ne teste pas la seconde.
Les expressions conditionnelles.
Une expression conditionnelle sert à réagir en fonction d'un élément donné.
Expression IF...THEN...ELSE.
En algorithmique :
 codice_34
se traduit en Ruby par :
 codice_35
La condition peut être une expression, à condition que celle-ci soit une expression booléenne (vrai ou faux), ou une valeur numérique (0 ayant valeur de faux).
donc :
 if (1)
équivaut à
 if (true)
qui équivaut à
 if (2 + 2 == 4)
de même :
 if (0)
équivaut à
 if (false)
qui équivaut à
 if (2 + 2 == 5)
Une expression conditionnelle peut être l'élément ouvrant d'un bloc, ou succéder à une expression si celle-ci tient sur une ligne, dans ce denier cas on ne peut utiliser "else" :
 if true
 puts "true"
 end => "true"
équivaut à
 puts "true" if true => "true"
Le pendant de "if" est "unless" (sauf si) et suit les mêmes règles, toutefois l'instruction n'est exécuté que si la condition est fausse :
 puts "false" unless false => "false"
À noter que pour faciliter la lecture, ruby permet de faire suivre l'expression testée du mot clef "then" :
 if (true) then
Expression CASE...WHEN.
codice_36
ce qui se traduit en ruby par :
codice_37
"case" va comparer l'expression le suivant avec les expressions passées après les mots-clefs "when". Si l'une d'elle correspond, case appelera l'expression suivant le "then". Sinon il évaluera l'expression suivant le "else" :
 chaine = "ça va ?"
 case chaine
 when "bonjour" then "bonjour"
 when "ça va ?" then "oui merci"
 else "au revoir"
 end => "oui merci"
À noter que l'expression suivant le "case" est facultative :
 age = 40
 case
 when ((age > 60) and (age < 100)) then "Vous êtes agé"
 when ((age <= 60) and (age > 15)) then "Vous êtes dans la fleur de l'age"
 when age <= 15 then "Vous êtes jeune"
 else "Mathusalem"
 end => "Vous êtes dans la fleur de l'age"
Si "age" avait été supérieur à 100, c'est la condition "else" qui aurait été prise en compte.
À noter que "then" peut être remplacé par le caractère deux points ( codice_38 ), on peut également mettre la clause "when" sur deux lignes :
 case 
 when ((age > 60) and (age < 100))
 "Vous êtes agé"
 end
Les boucles.
Les boucles permettent de parcourir une liste d'éléments, ou d'effectuer une action tant qu'une condition est respectée.
While/Until.
codice_39
ce qui se traduit en ruby par
codice_40
Par exemple :
 i = 0
 while (i < 5) 
 puts i
 i = i + 1
 end
 => 0
 1
 2
 3
 4
Dans cet exemple l'expression conditionnelle est évaluée avant l'évaluation du corps de la boucle, donc si i avait été égal à 6, le contenu de la boucle n'aurait jamais été évalué. Néanmoins nous pouvons utiliser une autre construction commençant par un bloc et suivit de "while", dans ce cas là le corps de la boucle est évalué au moins une fois :
 i = 12
 begin
 puts i
 i = i + 1
 end while (i < 5)
 => 12
La négation de while est until, que l'on pourrait traduire par "jusqu'à" :
 i = 0
 until (i > 5) 
 puts i
 i = i + 1
 end
 => 0
 1
 2
 3
 4
 5
loop.
"loop" ressemble à la structure while, mais ne prend pas d'expression conditionnelle. En fait "loop" correspond à
 while(true)
Le seul moyen de quitter la boucle est d'utiliser l'instruction break :
 i = 0
 loop do
 puts i
 i = i + 1
 break if i >= 5
 end
 => 0
 1
 2
 3
 4
For in.
La boucle "for" permet d'itérer à travers un ensemble :
 for i in 5..8
 puts i
 end
 => 5
 6
 7
 8
Nous verrons les intervalles (de forme x..y) dans le chapitre suivant, pour l'heure il suffit de savoir qu'ils représentent tous les éléments compris entre x et y.
Ceci est une manière d'itérer, néanmoins nous verrons dans les chapitres suivant qu'en ruby il vaut mieux itérer en utilisant les méthodes adaptées. Ainsi le même exemple aurait pu s'écrire :
 (5..8).each do |i|
 puts i
 end
Pour les chaînes de caractères, le retour chariot servira de séparateur :
 for ligne in "première\ndeuxième\ntroisième"
 puts ligne
 end
 => première
 deuxième
 troisième
Itérateurs.
un grand nombre d'objet en Ruby implémente des itérateurs, cad; des méthodes de parcours des éléments de l'objet lui-même.
each.
La boucle each (chaque en anglais) parcours tous les éléments d'un tableau en assignant à une variable temporaire l'élément actuel.
Soit dans une classe la va
 noms = ['toto', 'tata', 'titi']
 noms.each do |nom|
 puts "Salut #{nom} !"
 end
 => Salut toto !
 => Salut tata !
 => Salut titi !
each_byte et each_line.
Les chaînes de caractères ont une méthode spécifique appelée each_byte (chaque caractère) qui parcours la chaîne caractère par caractère :
 a
 b
 c
 d
 e
 f
Et each_line (chaque ligne) qui parcoure les lignes séparés par le retour chariot :
 => première
 suite
 autre
times.
Fonction typique à Ruby, la méthode d'itération des classes d'entiers nommée times (fois) et qui peut être utilisé avec les constantes numériques (ce langage étant pur objet) :
 => texte
 texte
 texte
ou bien :
 3.times do
 puts "texte"
 done
 => texte
 texte
 texte
Les mots clés de contrôle d'execution.
Parmi les rares mots clés du langage, on trouve un certain nombre de controles d'execution
Break.
Nous avons déjà vu "break" qui permet d'interrompre l'exécution d'une boucle :
 i = 0
 while (true)
 break if i > 3
 puts i
 i = i+1
 end
 => 0
 1
 2
 3
Redo.
"redo" va réévaluer le corps de la boucle, mais sans retester la condition, et sans utiliser l'élément suivant (dans un itérateur)
 for i in 1..4
 print "#{i} "
 if i==2
 i=0
 redo
 end
 puts i
 end
 => 1 1
 2 0 0
 3 3
 4 4
La variable i étant définie localement (dans la boucle), cela ne change pas le déroulement par rapport à la liste globale, mais la variable est bien vue comme ayant une valeur différente de 2 la seconde fois et le redo est évité. Le puts suivant le redo dans le bloc de code de la boucle n'est pas exécuté lorsque celui est exécuté.
Next.
"next" va aller à la fin de la boucle, puis recommencer l'itération avec l'élément suivant dans le cas d'un itérateur :
 i=0
 loop do
 i += 1
 next if i < 3
 puts i
 break if i > 4
 end
 => 3
 4
 5
Retry.
"retry" recommence l'itération à son début, dans son état premier :
 for i in 1..5
 puts i
 retry if i == 2
 end
 => 1
 2
 1
 2
On entre ici dans une boucle infinie.
Remarques.
Boucles implicites.
Le parcours des éléments d'un tableau dans Ruby est implicite lorsque on l'utilise comme variable d'assignation, comme c'est le cas pour les chaînes de caractère dans la majorité des langages :
 puts [ "élément 1", "élément 2", "élément 3" ]
 => élément 1
 élément 2
 élément 3
On peut de la même façon extraire une partie d'un tableau simplement sans avoir à créer de boucle qui parcoure tous les éléments.
Exemple tiré du site officiel de Ruby
 villes = %w[ Londres
 Oslo
 Paris
 Amsterdam
 Berlin ]
 visitees = %w[Berlin Oslo]
 puts "J'ai toujours besoin " +
 "de visiter les " +
 "villes suivantes :",
 villes - visitees
 => Londres
 Paris
 Amsterdam
Cet exemple sort les éléments du tableau qui sont dans les villes mais pas dans visitées