Racket pour les Rubyists 7: Module basique
La dernière fois, on a écrit notre première fonction en Racket. Et avant d’écrire des tests unitaires pour pouvoir la passer à la moulinette du refactoring, il faut explorer un peu les modules Racket.
La notion de module en Racket
Jusqu’ici on a utilisé le REPL, il est temps maintenant de mettre notre
code dans un fichier. Voyons le programme suivant, à mettre dans un
fichier foo.rkt
:
Vous reconnaissez la définition de deux fonctions: times-2
et times-3
qui multiplient respectivements leur argument par 2 et par 3. En plus de ça,
il y a trois éléments nouveaux:
Spécification d’un dialecte
La ligne #lang racket
spécifie à Racket le dialecte utilisé. Il y en a
plein et je n’utiliserais que celui-ci. Il faudra penser à toujours placé
cette ligne au début de chaque fichier.
Convention de nommage
Un petit exemple vaut mieux qu’un long discours:
thisIsJavaConvention
this_is_ruby_convention
this-is-racket-convention
La fonction provide
La fonction provide
, qu’on peut placer n’importe où dans le fichier (donc
au début ou à la fin), permet d’exporter les fonctions données en
argument. Les autres fonctions (celle qui ne sont pas données à provide
)
sont visible dans le fichier, mais pas à l’extérieur. Autrement dit,
provide
permet de spécifier l’API, les fonctions publiques.
Utilisation d’un module
Dans le REPL, démaré dans le même dossier que le fichier “foo.rkt”,
on utilise la fonction require
:
-> (require "foo.rkt")
On peut maintenant utiliser la fonction publique times-2
:
-> (times-2 9)
18
Et comme attendu, on ne peut pas utiliser times-3
:
-> (times-3 9)
; times-3: undefined;
; cannot reference undefined identifier
Comparaison avec les modules Ruby
Voici le pendant du fichier foo.rkt
écrit en Ruby:
Et voici comment on s’en sert dans une session irb:
Le comportement est assez similaire. Petite différence, Ruby oblige à définir
le fichier requis par rapport au dossier courant alors que Racket le fait
automatiquement (ok, j’aurais pu utiliser require_relative
…).
Mais la grande différence est qu’un module Ruby définit un espace de nom, pas un module Racket. À l’heure actuelle je ne sais pas si Racket possède un mécanisme pour les espaces de nom, je n’en suis pas encore là, mais j’espère que oui…
La prochaine fois, on verra comment faire des tests unitaires simples en Racket.
À demain.