(let pat (? init))
  pat: a pattern
  init: any form (optional)
  returns #n

Binds a local variable.

let plays the same role in GameLisp that it does in Rust: it introduces one or more new local variables into the current lexical scope.

(def x 100)

(defn example ()
  (prn x)  ; prints 100

  (let x 200)
  (prn x)  ; prints 200

    (let x 300)
    (prn x)) ; prints 300

  (prn x)) ; prints 200

If the init form is absent, each name defined by pat is initialized to #n.

Unlike Rust, pattern-bindings in let can be fallible. If the result of the init form does not match pat, an error occurs.

A single let form may bind multiple patterns to multiple initializers: (let a b c d e) is equivalent to (let a b), then (let c d), then (let e). You should usually separate multiple bindings using commas: (let a b, c d, e).

let must only appear at the toplevel, or as the immediate child of a do form, or immediately within an "implicit do". For example, providing a let form as an argument to a function call would be an error.