در 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)
})
})
})
})
}
عبارتهای use در Gleam به ما اجازه میدهند این کد را بدون تورفتگی بنویسیم و همین اغلب خواندنش را آسانتر میکند.
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)
}
عبارتهای use در Gleam ویژگی بسیار قدرتمندیاند که میتوان آنها را برای مسائل زیادی به کار برد، اما استفادهی بیش از حد از آنها میتواند کد را سختخوان کند. به طور کلی بهتر است از نحوهی نگارش معمول فراخوانی تابع استفاده کنید و فقط وقتی سراغ عبارتهای use بروید که خواندن کد را آسانتر میکنند.