TODO : Ce cours est composé uniquement des notes préparées avant la session. Il reste à intégrer les sujets discutées durant le cours depuis les logs.
Ruby est un langage de programmation. C'est un langage de haut niveau, interprété (contrairement au C par exemple qui doit être compilé avant de pouvoir être exécuté), et orienté objet. Il est utilisable facilement comme langage de script (programmation procédurale), à la manière de python ou perl, pour créer facilement de petits programmes, mais est bien sur également adapté pour mettre en place de gros sites Web ou des applications graphiques.
Son créateur est Yukihiro Matsumoto, alias Matz. Pour les plus curieux, il a inventé Ruby en 1993 car des langages tels que perl ou python ne le satisfaisaient pas,
en s'inspirant entre autres de Smalltalk.
Lors de sa création il a essayé de s'inspirer des principes de “moindre surprise”. Cela veut dire que si vous comprenez comment marche un composant du langage,
vous devriez pouvoir utiliser un composant similaire de la même manière (ne vous inquietez pas si vous ne comprenez pas ce concept pour le moment !
).
Petite note en passant, un cours sur ruby avait déjà été fait par FiFouille (le 14/03/2007), mais je recommence la série à zéro pour m'adresser aux débutants. Si vous êtes interréssé par ce premier cours les logs sont dispo sur le site.
Enfin avant de commencer sachez que pour ce cours je m'inspire du tutorial “ruby en vingt minutes” disponible ici http://www.ruby-lang.org/fr/documentation/quickstart/
ainsi que du cours de gpocentek sur python. Merci à eux
La version stable courante de ruby est ruby 1.8.7 (la version la plus utilisée est toutefois ruby 1.8.6. La version de développement est ruby 1.9.1).
Installons donc ruby. Sous ubuntu/debian on installera les paquets ruby et irb ou mieux, ruby-full qui dépend de ruby ainsi que d'autres paquets utiles. Parmi ceux-ci se trouve irb dont nous allons voir tout de suite l'utilité.
Irb (interactive RuBy) est un interpréteur de commandes, c'est à dire qu'on peut l'utiser à la manière d'un shell tel que bash pour y entrer du code ruby qui sera interprété directement, sans devoir passer par un fichier.
Ouvrez donc un terminal et lancez irb en tapant simplement `irb`.
Vous voila dans irb. Comme dans un shell classique, vous pouvez entrer du code en le tapant simplement puis en appuyant sur entrée. Essayons donc ! On va commencer par une utilisation simple, du calcul. Entrez dans votre interpréteur le code suivant :
2+2
Et validez donc par la touche entrée. irb nous affiche en retour
=> 4
Le ”⇒” signifie que ruby nous a renvoyé une valeur, 4. Essayons encore :
(20/20) * 20
Traditionellement en programmation `/` représente la division et `*` la multiplication.
(Notez que durant le cours, je préfixerait de 4 espaces le texte que vous aurez à entrer dans votre interpréteur.)
On vient donc d'écrire du code ruby, aussi simple soit-il. Précisement, le code `2+2` est une instruction qui est interprétée par ruby et 4 est le résultat de l'exécution de cette instruction. Essayez d'entrer simplement une valeur comme 2, vous verrez que le résultat donné par ruby sera bien évidemment 2.
J'imagine que vous voulez faire plus compliqué. Entrez donc le code suivant :
"Bonjour tout le monde"
(Je m'excuse par avance pour les pédants qui me feront la remarque que ceci n'est pas la traduction de “Hello world”) Ruby nous a donc donné en retour `”Bonjour tout le monde”`. Notez les guillemets qui sont importants comme nous allons voir cela.
Le calcul c'est bien joli, mais vous conviendrez que tout cela est assez éphémère. Nous allons donc utiliser des variables. Une variable sert à stocker des données diverses. Elles ont un nom (aussi appelé le symbole), et une valeur qui leur est attribué. Un nom de variable en ruby peut être composé de lettres (minuscules comme majuscules), chiffres et du tiret bas `_`. De plus, son nom _ne doit pas_ commencer par un chiffre ou une lettre majuscule.
Comment créer une variable ? C'est très simple :
nombre = 42
Ici on crée la variable nombre, et lui assigne la valeur 42 grâce à l'opérateur d'assignation `=` Essayons encore :
calcul = 2+2
La variable calcul se voit assigné le résultat de l'instruction `2+2`. Vérifiez par vous même :
calcul
Avec cette instruction ruby vous renvoie la valeur de `calcul`. Vous pouvez bien sur effectuer toutes sortes d'opération sur les variables, comme par exemple :
nombre - calcul
Ou même :
calcul = nombre - calcul
Remarquez ici que j'ai remplacé la valeur de la variable calcul par le résultat de l'opération `nombre - calcul`.
Une dernière chose !
mavariableinexistante
Ah, ça ne marche pas. Ruby vous a retourné une erreur (il a en fait précisément levé une exception de type `NameError`). Vous pouvez voir une description détaillée de l'erreur “undefined local variable or method `mavariableinexistante' for main:Object” et la ligne ou s'est produite l'erreur. Vous pouvez ignorer le “main:Object” pour le moment, remarquez par contre que l'erreur est assez explicite (“variable ou méthode locale indéfinie”). La ligne est utile lorsque l'erreur se produit dans un script pour savoir ou chercher dans notre fichier.
Je ne l'ai pas encore précisé mais les données que renferment une variable ont un “type”. Vous avez déjà vu deux types pour le moment, Integer (nombre entier) et String (une chaîne de caractère). Un type *nombre entier* ? Oui, regardez :
5/2
Oulah, `2` ! Ca a l'air faux. Qu'est-ce que ca veut dire ? En fait ruby a simplement remarqué que vous utilisez deux nombres entier, et vous a donc retourné un nombre entier. Pour cela il a tronqué le résultat de la division pour obtenir la valeur entière. Pour représenter un nombre à virgule en informatique on utilise des “nombres à virgule flottante”, plus communément appelés “flottant” ou nombre “flottant” (Float en ruby). Vous faire comprendre à ruby que votre nombre est un flottant comme ceci :
2.5
On peut donc utiliser l'astuce suivante :
flottant = 5.0
Le point `.` représente la virgule, et ruby comprend ici que l'on souhaite un nombre flottant. Ressayons la division de tout à l'heure :
flottant / 2
C'est gagné, ruby nous retourne un flottant. Remarquez aussi qu'il suffit d'un seul flottant à ruby sur les deux nombres pour comprend qu'il doit retourner un flottant. Ok, ca marche, mais… ?
2.0 / 3
Ouille, on obtient `0.666666666666667`. En effet (principalement pour des raisons de performance) le nombre de chiffres après la virgule que peut gérer un flottant est limité. Ruby a donc arrondi le résultat en essayant d'obtenir la meilleure précision possible.
Bref, passons à d'autres types, notamment le type String cité plus haut. Un string est donc une chaîne de caractères, soit comme son nom l'indique une série de… caractères :
chaine = "Voila du texte"
Votre variable `chaine` contient donc à présent la chaîne de caractères “Voila du texte”. Notez que les restrictions sur les noms de variable ne s'appliquent pas au contenu des strings. Un string peut être créé (entres autres) en utilisant les délimiteurs ”” et '' :
chaine2 = 'et encore du texte'
Les strings peuvent comme les entiers et les flottants subir diverses opérations :
chaine + chaine2
Pas mal, c'est presque bien. Encore mieux :
"-" * 20
Sympa non ? Et la soustraction ?
"texte" - "tex"
Ah non, ruby n'est quand même pas _si_ intelligent
Ruby nous indique que la méthode `-` n'existe pas pour les strings. Nous verrons plus tard ce qu'est une méthode en détail.
Une petite remarque qui a son importance, un String n'est pas du tout un nombre ! Essayez donc :
"2" + 2
Ruby nous dit ici qu'il ne peut changer un String en Fixnum (pour les petits curieux un Fixnum est “une sorte d'Integer”).
Y-a-t-il d'autres types ? Oui, plein ! Il faudrait plus d'une session pour voir les différents types que propose ruby. Mais voyons tout de même un autre type considéré comme basique dans les langages de script, les tableaux. Les tableaux, ou arrays, ont pour objectif de contenir un ensemble de valeurs. un exemple sera surement plus parlant :
notes = [12, 15, 8, 17, 5.5, "zero"]
Il s'agit donc d'un groupe de valeurs, qui peuvent être de n'importe quel type. Pour accéder à une valeur contenue dans un tableau on doit connaitre sa position (dite index) :
notes[0] notes[2]
Notez que la numérotation commence à 0. La dernière entrée d'un tableau de 6 valeurs est donc située à l'index 5. Il est aussi possible d'accéder à un tableau en partant de la fin, de cette manière :
notes[-1] notes[-2] #avant-dernier element
On peut ajouter des valeurs à un tableau :
notes << 10
La valeur renvoyée par ruby est la nouvelle valeur de votre tableau notes. On peut aussi ajouter des tableaux :
notes + [5, 12]
Notez ici que ce qu'affiche irb est simplement le résultat de l'opération, votre tableau n'ayant pas été modifié. La soustraction entre tableaux est également possible :
notes = notes - [5.5, "zero"]
Comme vous l'imaginez la position de chaque entrée du tableau peut donc varier durant l'exécution de votre programme.
Allez, un dernier type pour la route. Que se passe-t-il si l'on veut comparer des variables ?
4 > 2
Ruby nous a renvoyé `true`. Remarquez que ce n'est pas une chaîne de caractères (pas de guillemets). Essayons autre chose :
10 == 20
On obtient `false` maintenant. Notez que l'opérateur == sert à comparer si deux valeurs sont égales (le caractère = simple servant déjà à l'assignation).
Quelques autres opérateurs de comparaison : * != : différent (le contraire de l'égalité) * >= : supérieur ou égal * < : inférieur
Ces résultat `true` et `false` sont des booléens (boolean). Un booléen est une variable qui peut avoir deux états, vrai (true) ou faux (false). Nous verrons leur utilité (énorme !) lorsque nous aborderons les tests conditionnels.
Bien, nous savons maintenant nous servir d'irb et nous pouvons jouer avec les variables de différents types. On peut donc écrire notre premier vrai script ! Quittez irb en utilisant Control+D ou en tapant `exit` (ou encore `quit`) pour revenir à votre shell favori.
Nous allons donc écrire notre premier programme. Pour cela il vous faudra utiliser un éditeur de texte quelconque : vim, nano, gedit, geany… Créez donc un fichier que l'on pourra nommer par exemple “test_classroom.rb” et ouvrez le dans votre éditeur. L'extension .rb est une convention qui indique que ce fichier contient du code ruby, à la manière des fichiers .py (python).
Insérez le texte suivant dans votre fichier :
#!/usr/bin/env ruby
et sautez une ou deux lignes. Cette ligne totalement optionelle est appelée “shebang”, ce n'est pas du code ruby mais un indicateur qui permettra à votre shell de déterminer quel programme utiliser pour l'exécuter. Si vous l'omettez vous devrez lancer votre programme en utilisant la commande `ruby test_classroom.rb`; tandis que si vous rendez votre fichier exécutable vous pourrez utiliser la forme `./test_classroom.rb` grâce au shebang.
Entrons ensuite ce code :
prenom = "John"
nom = "Doe"
#Le nom complet nom_complet = prenom + " " + nom
#texte a afficher texte = "Bonjour " + nom_complet
Notez les lignes commencant par `#`, ce sont des commentaires. Ils sont ignorés par ruby et servent aux programmeurs qui veulent détailler certains points de leurs programmes.
Nous pouvons maintenant essayer d'exécuter notre programme selon une des méthodes citées ci-dessus $ ruby test_classroom.rb
Et voila que… Ça n'a pas l'air de marcher ? En fait, si. Seulement on a oublié de demander a ruby d'afficher notre texte ! Corrigeons donc cet oubli en ajoutant après notre création de variable texte :
puts texte
Et relancons notre programme. Youpi ! Mais qu'est-ce que ce `puts` ? C'est une fonction. Les fonctions sont des concepts très importants comme nous allons le voir tout de suite.
Continuons un peu notre script pour le rendre interactif. Modifiez la ligne `prenom = “John”` par :
prenom = gets.chomp
Et relancez votre programme. Vous avez l'impression que ruby bloque mais il attends simplement une entrée. Tapez donc votre prénom suivi de la touche entrée. Ainsi `gets` nous a permis de récupérer le texte entré (j'expliquerai le rôle de chomp plus tard).
Des instructions telles que puts et chomp sont donc des fonctions. On vient de voir que puts sert à afficher du texte, et gets à en obtenir depuis l'entrée standard.
Pour appeler une fonction il suffit d'entrer son nom, suivi si nécessaire d'une liste de valeurs appelés “arguments” ou encore “paramètres”. Les arguments seront passés à la fonction qui pourra les réutiliser.
Pour appeler une fonction on utilise donc traditionellement la forme suivante : mafonction(argument1, argument2)
Mais ruby nous facilite la vie en rendant les parenthèses inutiles la plupart du temps. On peut donc utiliser : mafonction argument1, argument2 Ou même simplement `mafonction` si celle ci ne prend pas de paramètres.
Essayons maintenant de définir une fonction. Vous pouvez revenir dans irb, ou ouvrir un nouveau fichier pour entrer le code suivant :
def dit_bonjour()
puts "Salut !"
end
Vous pouvez maintenant appeler votre fonction en utilisant `dit_bonjour`, ou `dit_bonjour()`. Le `def` est un mot-clé qui sert comme son nom l'indique à établir une définition. `end` marque lui la fin de cette définition. L'indentation (le fait d'ajouter des caractères espaces ou tabluation devant du code) n'est pas nécessaire (contrairement à python), mais elle est recommandée et extrèmement utile pour avoir un code clair et aéré. Notez que le nom d'une fonction est important, il doit être explicite sous peine de devoir ajouter des commentaires afin de comprendre son code. Remarquez aussi que les parenthèses sont ici optionnelles de la même manière que dans l'appel d'une fonction. La définition d'une fonction ressemble donc fortement à son appel.
Essayons à présent une fonction qui prend deux paramètres :
def nom_complet(prenom, nom)
return "#{prenom} #{nom}"
end
Je viens également d'introduire un autre concept en ruby : à l'intérieur d'un string, on peut utiliser #{} pour appeler du code ruby (ici des variables) qui sera inséré à cet endroit. Notez qu'il faut déclarer notre string en utilisant les guillemets doubles pour pouvoir utiliser cette fonctionnalité. Vous voyez ici l'utilisation du mot-clé return. Utilisé dans une fonction, cette instruction arrête son exécution (si il reste du code après cette directive, celui-ci ne sera pas executé) et retourne la valeur spécifiée. Nous nous sommes déjà servi du mécanisme de renvoi de valeurs :
a = 2+2
Assigne à la variable `a` la valeur renvoyée par l'instruction 2+2. Vous en déduisez donc que l'on peut faire :
mon_nom = nom_complet("John", "Doe")
Sachez aussi que ruby a une particularité, qui est de renvoyer la valeur de la dernière instruction présente dans une fonction si aucun mot-clé return n'est rencontré. Par exemple :
def double val
val * 2
end
En essayant
double 8
On obtiendra bien 16 qui est la valeur renvoyée par l'instruction `val * 2` lorsque val est égale à 8.
Il y a bien d'autres choses à dire sur les fonctions, mais ce que l'on a appris ici devrait être suffisant pour la suite du cours.
Une petite remarque toutefois, essayez dans irb :
puts "test"
Vous verrez que irb renvoie `nil`. En ruby, `nil` représente l'absence totale de valeur, et vous le rencontrerez à de nombreuses reprises.
Les tests conditionnels sont également un concept de base en programmation. Il servent à effectuer des actions selon le résultat d'une instruction. La syntaxe d'un test basique est la suivante :
if(4 > 2)
puts "4 est plus grand que 2"
end
Ce code peut se lire ainsi : Si 4 est supérieur à 2, exécuter le code `puts “4 est plus grand que 2”`. C'est avec les tests conditionnels que les booléens vu plus haut prennent toute leur utilité. Notez également le `end` qui sert bien à délimiter des blocs de code.
Un test conditionnel ne se limite pas au if, on peut également exécuter du code si la condition n'est pas remplie, comme ceci :
if user_is_authorized
puts "Accès autorisé"
else
puts "Accès interdit"
end
On peut également utiliser `elsif` pour exécuter un autre test si le premier échoue :
if age >= 18
personne = "majeur"
elsif age >= 16
personne = "de 16 à 18 ans"
else
personne = "moins de 16 ans"
end
(Le dernier else étant optionnel si vous n'en avez pas besoin.)
Vous vous demandez peut-être maintenant comment tester le contraire d'une expression, sans passer par `else`. Pour cela vous pouvez utiliser l'opérateur `!` (appelé “bang”), présent dans tous les langages classiques, comme ceci :
if !user_is_authorized
puts "Accès interdit"
end
Mais ruby peut faire mieux. Il propose en effet l'instruction `unless` :
unless user_is_authorized
puts "Accès interdit"
end
On peut également compléter cela avec un `else` (mais pas elsif).
Avant de nous quitter, sachez que vous pouvez gagner du temps dans l'utilisation d'irb en activant des fonctionnalités avancées de l'interpréteur. Pour cela il vous faudra modifier votre fichier ~/.irbrc pour y ajouter des options, à la manière d'un bashrc. Vous trouverez un exemple de fichier irbrc ici : http://gist.github.com/104140 pour activer entre autres l'autocomplétion et un fichier d'historique de commandes.
Il est maintenant temps de nous quitter. Vous êtes à présent équipés (je l'espère) de quelques unes des connaissances de base nécessaires à la création d'un programme informatique. J'ai malheureusement dû omettre de grosses parts du langage et des concepts de la programmation (avec entre autres évidemment les boucles, les classes…). Ce cours est donc seulement le début d'une série sur le sujet, et j'espère vous retrouver pour la suite du programme ! N'hésitez pas à nous donner votre feedback sur ce cours (ici, ou sur le blog), ou vos suggestions, afin de mieux orienter les suivants.
Enfin sachez que les logs et le cours seront disponibles rapidement sur notre site http://u-classroom.net
Merci de m'avoir suivi