Lazy Value

If you have some expensive computations you'd like to defer and cache subsequently, you can turn them into lazy values:

ReScriptJS Output
@module("node:fs")
external readdirSync: string => array<string> = "readdirSync"

// Read the directory, only once
let expensiveFilesRead = Lazy.make(() => {
  Console.log("Reading dir")
  readdirSync("./pages")
})

Note: a lazy value is not a shared data type. Don't rely on its runtime representation in your JavaScript code.

Execute The Lazy Computation

To actually run the lazy value's computation, use Lazy.get from the standard library Lazy module:

ReScriptJS Output
// First call. The computation happens
Console.log(Lazy.get(expensiveFilesRead)) // logs "Reading dir" and the directory content

// Second call. Will just return the already calculated result
Console.log(Lazy.get(expensiveFilesRead)) // logs the directory content

The first time Lazy.get is called, the expensive computation happens and the result is cached. The second time, the cached value is directly used.

You can't re-trigger the computation after the first get call. Make sure you only use a lazy value with computations whose results don't change (e.g. an expensive server request whose response is always the same).

Exception Handling

For completeness' sake, our files read example might throw an exception because of readdirSync. Here's how you'd handle it:

ReScriptJS Output
let result = try {
  Lazy.get(expensiveFilesRead)
} catch {
| Not_found => [] // empty array of files
}

Though you should probably handle the exception inside the lazy computation itself.