Un Goloiste peut il ĂȘtre plus fonctionnel quâun Scalafiste?
CĂ©dric Beust, dans le dernier podcast des CastCodeurs, explique le point de vue de la programmation fonctionnelle de cette façon: quand une fonction lance une exception elle ne retourne pas une valeur et ça casse le raisonnement fonctionnel, donc il faut pouvoir toujours retourner âquelque choseâ, par exemple retourner un type T si tout va bien ou un type E (ou une variante du type T) si il y a une erreur. Ce qui permet de continuer le âraisonnementâ fonctionnel dans votre code. Tout ça est mon interprĂ©tation des paroles de CĂ©dric Beust bien sĂ»r.
Ces concepts sont faciles Ă mettre en oeuvre avec le langage Golo. Pour rappel, Golo est un langage dynamique pour la JVM, il est tout petit (530kb) mais il peut dĂ©jĂ jouer dans la cour des grands. Ses multiples influences lui apportent de nombreuses possibilitĂ©s et notamment dans sa capacitĂ© Ă ĂȘtre âaugmentĂ©â.
Nous allons donc voir comment mettre en oeuvre des fonctions qui en cas dâerreur retournent quand mĂȘme quelque chose quoiquâil se passe (je traiterais aussi la notion de valeur null).
Traiter âfontionnellementâ mes exceptions, partie 1
Ma premiĂšre spĂ©cification va donc ĂȘtre la suivante:
- Permettre Ă mes fonctions de pouvoir retourner un type T dont lâinstance peut avoir une valeur ou une erreur.
En Golo, on a des structures, du coup mon type sera le suivant:
Et je peux ensuite lâinstancier de cette maniĂšre:
GĂ©rer les valeurs null
Il se trouve quâen Golo, il est possible de greffer des mĂ©thodes aux structures avec le mot clĂ© augment
. Je vais donc ajouter une méthode getOrElse
à ma structure pour gérer les valeurs null
:
Cela signifie que je vais pouvoir Ă©crire ceci:
ou ceci en passant une fonction anonyme dont le paramĂštre est la rĂ©fĂ©rence Ă lâinstance de type:
Remarque: en Golo il existe le mot clé orIfNull
qui permet de gĂ©rer ça facilement, mais jâai fait comme cela pour introduire la suite.
GĂ©rer les exceptions
Il est tout Ă fait possible de surcharger une mĂ©thode dâaugmentation, donc on va augmenter encore plus notre structure en gĂ©rant un comportement en cas dâexception.
Cela sâutilisera dans le mĂȘme principe que la gestion des valeurs null
. Codons une méthode divide
qui va faire une division:
Et je pourrais utiliser ma fonction de cette maniĂšre:
Jâai gĂ©nĂ©rĂ© une exception car je fais une division par 0, mais je nâarrĂȘte pas mon programme et d
a tout de mĂȘme une valeur.
Comme précédemment je peux aussi faire ceci:
LĂ je commence Ă ĂȘtre fier de moi (un peu dâautosatisfaction ne fait pas de mal), mais je trouve que le try catch finally
câest laid Ă lire, je vais donc utiliser une nouveautĂ© de Golo pour faire encore mieux.
Traiter âfontionnellementâ mes exceptions, partie 2
Depuis peu, on trouve la notion de decorator (façon Python) dans Golo. Cela correspond Ă âdĂ©corerâ une fonction avec une autre fonction, ce qui permet dâagir avant et aprĂšs lâexĂ©cution dâune fonction (pas clair ? Avec un exemple ça ira (peut-ĂȘtre) mieux).
Mon objectif est de âvirerâ le try catch finally
du corps de mes méthodes. Je vais donc faire un decorator:
Alors:
withGoloType
câest ma fonction decoratorfunc
dansreturn |func|
câest la fonction retournĂ©e
Globalement je fais des traitements et je peux invoquer ma fonction comme ceci: func: invokeWithArguments(functionArgs)
Dans mon cas,
- jâinstancie un type
T
:let ret = T(null, null)
- ensuite âjâessayeâ de renseigner la propriĂ©tĂ©
value
deret
avec le résultat de la fonction décorée:ret: value(func: invokeWithArguments(functionArgs))
- si ça se passe mal, je âstockeâ lâexception:
ret: error(e)
- et au final je retourne mon instance de type
Et cela sâutilise comme ceci:
Une fois décorée, divide
ne retournera plus de valeur numérique, mais un type T qui permettra de fournir une valeur avac sa méthode getOrElse
.
VoilĂ , vous venez de voir comment il est trĂšs facile dâapporter de nouveaux comportements Ă Golo et de faire du fonctionnel avec (câest un moyen, il y en a beaucoup dâautres, mais ce sera pour de prochains articles).
@+ P.
Tweet