在 Gleam 中,编写和使用高阶函数很常见,也就是把其他函数作为实参的函数。有时同时使用多个高阶函数,代码会变得难以阅读,出现一层又一层的缩进。
例如,下面这个函数调用了几个返回 Result(Int, Nil) 的函数,并在四个都成功时把它们的值相加。
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)
})
})
})
})
}
Gleam 的 use 表达式让我们不用缩进就能写出这段代码,通常也更容易阅读。
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)
}
use 表达式会把代码块中随后的所有语句收集起来,作为一个回调函数,作为最后一个实参传给这次函数调用。use 关键字和 <- 符号之间的变量,就是将要传给回调函数的实参的名字。
// 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
})
回调函数可以接收任意数量的实参,也可以一个都不接收。
use a, b, c, d <- call_4_function()
use <- call_0_function()
要想创建能用 use 表达式调用的函数,除了把回调函数作为最后一个实参之外,没有其他特殊要求。
pub fn call_twice(function: fn() -> t) -> #(t, t) {
let first = function()
let second = function()
#(first, second)
}
Gleam 的 use 表达式是一个非常强大的功能,可以用于解决很多问题,但用得过多反而会让代码难以阅读。通常更推荐使用普通的函数调用语法,只有当 use 表达式能让代码更易读时才去使用它。
Daphne 一直在开发一个系统,用来运行并记录她的实验结果。有些代码变得有点冗长、重复,所以她请你写一些use表达式来帮忙精简一下。
with_retry函数有时实验会因为一次性的失误而失败,所以如果实验失败了,Daphne 想再重试一次,看看第二次能不能成功。
定义with_retry函数,它接受一个返回结果的函数作为实参。
如果这个函数返回Ok值,那么with_retry应该返回该值。
如果这个函数返回Error值,那么with_retry应该再次调用这个函数,并返回那次调用的结果。
Daphne 会这样使用这个函数:
pub fn main() {
use <- with_retry
// Perform the experiment here
}
record_timing函数Daphne 通过在每次实验前后调用一个记录时间的函数,来记录每个实验运行了多久。
定义record_timing函数,它接受两个实参:
Nil。record_timing应该先调用记录时间的函数,然后调用实验函数,接着再次调用记录时间的函数,最后返回实验函数的结果。
Daphne 会这样使用这个函数:
pub fn main() {
use <- record_timing(time_logger)
// Perform the experiment here
}
run_experiment函数实验由三个阶段组成:设置、操作和记录。三个阶段都会返回结果,而且每个阶段都需要上一个阶段的成功结果才能运行。
定义run_experiment函数,它接受四个实参:
String。Ok值作为实参,并返回一个结果。Ok值作为实参,并返回一个结果。如果这三个函数都成功,那么run_experiment应该返回Ok(#(experiment_name, recording_data))。
如果其中任何一个函数返回Error值,那么run_experiment应该返回该值。
Daphne 会这样使用这个函数:
pub fn main() {
use setup_data, action_data <- run_experiment("Test 1", setup, action)
// Record the results here
}