مسیرها
/
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)
        })
      })
    })
  })
}

عبارت‌های 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 همه‌ی دستورهای بعدی بلوک را جمع می‌کند و آن‌ها را به شکل یک تابع callback، به‌عنوان آخرین آرگومان، به فراخوانی تابع می‌فرستد. متغیرهای میان کلیدواژه‌ی use و نماد <- اسم آرگومان‌هایی هستند که به تابع callback فرستاده می‌شوند.

// 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
})

تابع callback می‌تواند هر تعداد آرگومان بگیرد، یا هیچ آرگومانی نگیرد.

use a, b, c, d <- call_4_function()

use <- call_0_function()

برای ساختن تابعی که بتوان آن را با یک عبارت use فراخوانی کرد، هیچ شرط خاصی وجود ندارد، جز اینکه یک تابع callback را به‌عنوان آخرین آرگومان بگیرد.

pub fn call_twice(function: fn() -> t) -> #(t, t) {
  let first = function()
  let second = function()
  #(first, second)
}

عبارت‌های use در Gleam قابلیت بسیار قدرتمندی هستند که می‌توان آن‌ها را برای مسائل زیادی به کار برد، اما اگر بیش از حد استفاده شوند، می‌توانند خواندن کد را دشوار کنند. به‌طور کلی بهتر است از نحوه‌ی نگارش معمول فراخوانی تابع استفاده کنید و فقط وقتی سراغ عبارت‌های use بروید که خواندن کد را آسان‌تر می‌کنند.

دستورالعمل‌ها

دافنه روی سیستمی برای اجرا و ثبت نتایج آزمایش‌هایش کار می‌کرده است. بخشی از کد کمی طولانی و تکراری شده است، بنابراین از شما خواسته است چند عبارت use بنویسید تا به تمیزتر شدن آن کمک کنید.

1. تعریف تابع with_retry

گاهی آزمایش‌ها ممکن است به دلیل یک اشتباه یک‌باره شکست بخورند؛ بنابراین اگر آزمایشی شکست بخورد، دافنه می‌خواهد دوباره آن را امتحان کند تا ببیند بار دوم کار می‌کند یا نه.

تابع with_retry را تعریف کنید. این تابع، تابعی را به عنوان آرگومان می‌گیرد که نتیجه برمی‌گرداند.

اگر تابع مقدار Ok را برگرداند، with_retry باید همان مقدار را برگرداند.

اگر تابع مقدار Error را برگرداند، with_retry باید دوباره تابع را فراخوانی کند و نتیجه‌ی آن فراخوانی را برگرداند.

دافنه از این تابع به این شکل استفاده می‌کند:

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

2. تعریف تابع record_timing

دافنه مدت زمان اجرای هر آزمایش را با فراخوانی یک تابع ثبت زمان، قبل و بعد از هر آزمایش، ثبت می‌کند.

تابع record_timing را تعریف کنید که دو آرگومان می‌گیرد:

  • تابع ثبت زمان که هیچ آرگومانی نمی‌گیرد و Nil را برمی‌گرداند.
  • تابع آزمایش که هیچ آرگومانی نمی‌گیرد و نتیجه‌ای برمی‌گرداند.

record_timing باید تابع ثبت زمان را فراخوانی کند، سپس تابع آزمایش را فراخوانی کند، بعد دوباره تابع ثبت زمان را فراخوانی کند و در پایان نتیجه‌ی تابع آزمایش را برگرداند.

دافنه از این تابع به این شکل استفاده می‌کند:

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 باید همان مقدار را برگرداند.

دافنه از این تابع به این شکل استفاده می‌کند:

pub fn main() {
  use setup_data, action_data <- run_experiment("Test 1", setup, action)
  // Record the results here
}
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Gleam Exercism

آماده‌اید آزمایش‌های تخصصی را شروع کنید؟

در Exercism ثبت‌نام کنید تا Gleam را همراه با 33 مفهوم122 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.