學習軌道
/
Gleam
Gleam
/
練習
/
專家實驗
專家實驗

專家實驗

學習練習

簡介

使用use運算式

在 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運算式來幫忙整理。

1. 定義with_retry函式

有時候實驗可能會因為一次偶發的失誤而失敗,所以如果實驗失敗了,Daphne 想再重試一次,看看第二次是否會成功。

定義with_retry函式,它接受一個會回傳結果的函式作為引數。

如果這個函式回傳Ok值,with_retry就應該回傳那個值。

如果這個函式回傳Error值,with_retry就應該再次呼叫這個函式,並回傳那次呼叫的結果。

Daphne 會這樣使用這個函式:

pub fn main() {
  use <- with_retry
  // Perform the experiment here
}

2. 定義record_timing函式

Daphne 會在每個實驗前後呼叫記錄時間的函式,藉此記錄每個實驗執行所需的時間。

定義record_timing函式,它接受兩個引數:

  • 一個記錄時間的函式,它不接受任何引數,並回傳Nil。
  • 一個實驗函式,它不接受任何引數,並回傳結果。

record_timing應該先呼叫記錄時間的函式,接著呼叫實驗函式,然後再次呼叫記錄時間的函式,最後回傳實驗函式的結果。

Daphne 會這樣使用這個函式:

pub fn main() {
  use <- record_timing(time_logger)
  // Perform the experiment here
}

3. 定義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
}
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Gleam Exercism

準備好開始 專家實驗 了嗎?

註冊 Exercism,透過 33 個概念122 個練習 和真人引導來學習並精通 Gleam,全部免費。