Mon premier programme Elixir
Pour apprendre Elixir, j’ai décidé de faire quelques tâches tirées du rosetta code. Pour mon tout premier programme, je commence avec un classique: 99 bottles of beer.
Vous connaissez la chanson ? Le but du jeu est d’obtenir ça:
99 bottles of beer on the wall
99 bottles of beer
Take one down, pass it around
98 bottle of beer on the wall
...
1 bottle of beer on the wall
1 bottle of beer
Take one down, pass it around
0 bottles of beer on the wall
C’est parti. - N’oubliez pas que c’est mon premier programme Elixir, le code sera forcement maladroit. - D’abord une version sans tenir compte du pluriel de “bottle”.
Enum.each 99..1, fn idx ->
IO.puts "#{idx} bottles of beer on the wall"
IO.puts "#{idx} bottles of beer"
IO.puts "Take one down, pass it around"
IO.puts "#{idx - 1} bottles of beer on the wall"
IO.puts ""
end
On lance le programme comme ça:
elixir 99_bottle_of_beer_v1.exs
Il y a pas mal de ressemblance avec Ruby. Notamment, l’interpolation des chaînes de caractères est identique:
IO.puts "#{idx} bottles of beer on the wall"
La fameuse méthode puts
de Ruby est utilisée pour sortir du texte.
Le fait que puts
soit appelée d’un module IO
me rappelle un peu
Java.
Voyons maintenant l’itération:
Enum.each 99..1, fn idx ->
# ...
end
Tiens, on a déjà un truc qui ressemble à un pattern: Module.méthode
. On
a vu IO.puts
, on a maintenant Enum.each
. On va donc itérer sur un range
99..1
, et appliquer une fonction à chaque élément de ce range. La
fonction, anonyme, avec un argument, débute par fn idx ->
; idx
prenant
à chaque itération la valeur de l’élément courant du range.
Je m’intéresse maintenant à une version qui tient compte du pluriel.
defmodule Bottles do
def run do
Enum.each 99..1, fn idx ->
IO.puts "#{idx} bottle#{plural(idx)} of beer on the wall"
IO.puts "#{idx} bottle#{plural(idx)} of beer"
IO.puts "Take one down, pass it around"
IO.puts "#{idx - 1} bottle#{plural(idx-1)} of beer on the wall"
IO.puts ""
end
end
def plural num do
if num == 1 do
""
else
"s"
end
end
end
Bottles.run
J’ai du enfermer mes fonctions dans un module, avec defmodule
, puisqu’il
n’est pas permis d’utiliser def
en dehors d’un module. L’intérieur de
la fonction run
ne diffère pas vraiment de la version précédente.
La fonction plural
est intéressante à commenter:
def plural num do
if num == 1 do
""
else
"s"
end
end
Comme avec Ruby, les arguments n’ont pas besoin d’être enfermés entre
parenthèses, mais on peut le faire. Pas besoin non plus d’un mot-clé
return
, une fonction renvoie toujours une valeur, même de manière
implicite. Pour définir une fonction on utilise:
def name args do
. Le if
prends aussi un do
à la fin. Elixir semble
en fait être assez cohérent et homogène:
defmodule ... do ... end
def ... do ... end
if ... do ... end
Enfin, l’appel de la fonction run
est sans surprise: Bottles.run
. Je note
que je ne sais pas encore à quoi j’ai affaire avec les modules. Est-ce-qu’un
module est juste un espace de nommage ? Est-ce-qu’un module est plus qu’un
espace de nommage ?
Voilà pour une première approche d’Elixir, un langage qui ressemble beaucoup à Ruby, et en même temps pas vraiment ;)
À demain.