En Gleam, il est courant d'écrire et d'utiliser des fonctions d'ordre supérieur, c'est-à-dire des fonctions qui prennent d'autres fonctions en arguments. Parfois, lorsqu'on utilise de nombreuses fonctions d'ordre supérieur en même temps, le code peut devenir difficile à lire, avec de nombreuses couches d'indentation.
Par exemple, voici une fonction qui appelle plusieurs fonctions qui renvoient Result(Int, Nil), et additionne les valeurs si les quatre réussissent.
import gleam/result
pub fn main() -> Result(Int, Nil) {
result.try(function1(), fn(a) {
result.try(function2(), fn(b) {
result.try(function3(), fn(c) {
result.try(function4(), fn(d) {
Ok(a + b + c + d)
})
})
})
})
}
Les expressions use de Gleam permettent d'écrire ce code sans l'indentation, ce qui le rend souvent plus facile à lire.
import gleam/result
pub fn main() -> Result(Int, Nil) {
use a <- result.try(function1())
use b <- result.try(function2())
use c <- result.try(function3())
use d <- result.try(function4())
Ok(a + b + c + d)
}
Une expression use rassemble toutes les instructions suivantes du bloc et les passe sous forme de fonction de rappel comme dernier argument de l'appel de fonction. Les variables entre le mot-clé use et le symbole <- sont les noms des arguments qui seront passés à la fonction de rappel.
// This use expression
use a <- function(1, 2)
io.println("Hello!")
a
// Is equivalent to this normal function call
function(1, 2, fn(a) {
io.println("Hello!")
a
})
La fonction de rappel peut prendre n'importe quel nombre d'arguments, ou aucun.
use a, b, c, d <- call_4_function()
use <- call_0_function()
Il n'y a pas d'exigences particulières pour créer une fonction qui peut être appelée avec une expression use, si ce n'est qu'elle prend une fonction de rappel comme dernier argument.
pub fn call_twice(function: fn() -> t) -> #(t, t) {
let first = function()
let second = function()
#(first, second)
}
Les expressions use de Gleam sont une fonctionnalité très puissante qui peut s'appliquer à beaucoup de problèmes, mais lorsqu'on en abuse, elles peuvent rendre le code difficile à lire. Il est généralement préférable d'utiliser la syntaxe d'appel de fonction normale et de ne recourir aux expressions use que lorsqu'elles rendent le code plus facile à lire.
Daphne travaille sur un système qui exécute et enregistre les résultats de ses expériences. Une partie du code est devenue un peu verbeuse et répétitive, alors elle t'a demandé d'écrire quelques expressions use pour l'aider à le nettoyer.
with_retry
Il arrive qu'une expérience échoue à cause d'une erreur ponctuelle ; dans ce cas, Daphne veut la relancer pour voir si elle fonctionne du deuxième coup.
Définis la fonction with_retry, qui prend en argument une fonction qui renvoie un résultat.
Si la fonction renvoie une valeur Ok, alors with_retry doit renvoyer cette valeur.
Si la fonction renvoie une valeur Error, alors with_retry doit rappeler la fonction et renvoyer le résultat de cet appel.
Daphne utilisera la fonction comme ceci :
pub fn main() {
use <- with_retry
// Perform the experiment here
}
record_timing
Daphne enregistre la durée d'exécution de chaque expérience en appelant une fonction de journalisation du temps avant et après chaque expérience.
Définis la fonction record_timing, qui prend deux arguments :
Nil.record_timing doit appeler la fonction de journalisation du temps, puis appeler la fonction d'expérience, puis appeler à nouveau la fonction de journalisation du temps, et enfin renvoyer le résultat de la fonction d'expérience.
Daphne utilisera la fonction comme ceci :
pub fn main() {
use <- record_timing(time_logger)
// Perform the experiment here
}
run_experiment
Une expérience se déroule en trois phases. La préparation, l'action et l'enregistrement. Les trois phases renvoient un résultat, et pour s'exécuter, chacune a besoin que la phase précédente ait renvoyé un résultat positif.
Définis la fonction run_experiment, qui prend quatre arguments :
String.Ok de la fonction de préparation et renvoie un résultat.Ok des fonctions de préparation et d'action et renvoie un résultat.Si les trois fonctions réussissent, alors run_experiment doit renvoyer Ok(#(experiment_name, recording_data)).
Si l'une des fonctions renvoie une valeur Error, alors run_experiment doit renvoyer cette valeur.
Daphne utilisera la fonction comme ceci :
pub fn main() {
use setup_data, action_data <- run_experiment("Test 1", setup, action)
// Record the results here
}
Inscris-toi sur Exercism pour apprendre et maîtriser Gleam avec 33 concepts122 exercices, et un vrai mentorat humain, le tout gratuitement.