( For non-french readers : I am not giving up writing in english … Read the next post! )
Si vous venez d’un autre langage, le terme procédure (associé au terme fonction) doit vous dire quelque chose. Vaguement ….
Allez quelques connaissances (méconnaissances) tirées de ma mémoire pour poser les bases.
Par exemple, en PHP il existe deux types de fonctions. Les fonctions natives (built-in) et les fonctions “codées” par l’utilisateur.
Ces dernières se séparent en deux types : les fonctions et les procédures.
La différence entre les deux ? Une procédure est un groupe d’instructions qui ne renvoie pas de valeur. Une fonction est une procédure qui renvoie une valeur.
Et ruby dans tout ça ??
C’est complètement différent et je dirai même plus les procédures Ruby sont très éloignés des procédures PHP. En ruby il n’y a que des objets (les méthodes sont des objets) et les méthodes renvoient toujours une valeur.
Vous avez déjà vu ou même codé des choses comme ceci :
[1,2,3,4,5,6].each do |nb| # Un code quelconque : des instructions ... end
C’ette méthode est native à Enumerable (module que la classe Array inclut)
La méthode Array#each prend 0 paramètre mais un block. Le block est tout ce qui se trouve entre do et end.
On pourrait le représenter en Ruby comme ceci :
def each(&block) # Un truc compliqué à écrire en ruby end
Ne vous y trompez pas “&block” n’est pas un argument. C’est la notation ruby pour dire que la méthode each s’accompagne obligatoirement d’un block.
Autre exemple :
class Bar def my_proc(&procedure) @foo_proc = procedure end def recall @foo_proc.call end end bar = Bar.new bar.my_proc do # Pas de code end #=> #<Proc:0x00000>
Il se trouve que la procédure est une instance de la classe Proc.
Sans trop de surprise mêmes les procédures sont des objets. Et oui, en ruby tout est objet.
Quel est l’intérêt me direz-vous?
Cela change tout !!! En PHP les prcoédures sont codées en dur, en ruby on peut générer à la volée des suites d’instructions sans pour autant avoir à implémenter une méthode !!!
Illustration :
On sait que les blocks sont des instances de la classe Proc. La solution est facile, il suffit de créer des instances de Proc et les passer comme blocks d’une méthode acceptant un block.
p1 = Proc.new do puts "Je suis p1" end p2 = Proc.new do puts "Je suis p2" end bar = Bar.new bar.my_proc(&p1) # Je suis p1 #=> nil bar.foo_proc #=> #<Proc:0x164564ab> bar.recall # Je suis p1 #=> nil bar.my_proc(&p2) # Je suis p2 #=> #<Proc:0x054ecdab> bar.recall # Je suis p2 #=> nil bar2 = Bar.new bar2.my_proc(&p2) # Je suis p2 #=> #<Proc:0x054ecdab> bar2.instance_eval("@foo_proc") == bar.instance_eval("@foo_proc") #=> true
Vous avez compris l’intérêt? Les blocks sont bien des suites d’instructions mais plus que cela, ce sont des objets !!! L’illustration précédente montre qu’on peut partager des suites d’instructions entre différents objets, générer ces instructions dynamiquement !
En route pour la méta-programmation avec Ruby !!!

