liveBook · Manning

Let form

As explained in Clojure: The Essential Reference

let* is the Clojure special form that parses and validates the sequential bindings used internally by let.

A let form creates local names for evaluated expressions within a lexical scope. Each bound expression is evaluated once, and the resulting name can be reused without re-evaluation. The bindings are immutable; a later binding may shadow an earlier one without mutating it. section 3.1 section 3.1.1

Use the following contract to read and construct a let form:

  • Write a possibly empty vector containing an even number of elements: binding expression, value expression, and so on. section 3.1.1
  • Place valid binding expressions at even indexes; destructuring is allowed. section 3.1.1
  • Treat the remaining expressions as the body; multiple body expressions are implicitly wrapped in do. section 3.1.1
  • Return the last body expression, or nil when the body is empty. section 3.1.1
  • Avoid primitive type hints on local bindings such as ^long i; let recognizes primitive locals and rejects this hint with UnsupportedOperationException. section 3.1.1

Bind a random result once

(let [x (rand-int 10)] (if (>= x 5) (str x " is above the average") (str x " is below the average"))) Here, both branches use the same value of x rather than evaluating rand-int again. section 3.1.1

let and let*

let is the user-facing macro. let* is the special form that let uses internally to parse and validate its bindings, so direct use of let* normally offers no specific benefit. A let form is closely equivalent to invoking an anonymous function with the bound values as parameters. section 3.1.1 section 3.1

How Clojure: The Essential Reference covers it

How deep it goes
Defines the binding contract, return behavior, implicit do body, destructuring, immutability, and a primitive-hint exception.
Examples
Demonstrates one-time random evaluation, conditional formatting, destructured game moves, macro expansion, and generated large bindings.
What it assumes
Assumes basic Clojure expressions and vectors while defining lexical scope, immutable binding, and destructuring behavior.
What you can do after
Apply it via Clojure to name intermediate values, structure lexical scope, and return a body result.
How it connects
Connects lexical binding with destructuring, anonymous functions, macros, special forms, and lexical scope.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Clojure: The Essential Reference. The section links point to the parts of the book it draws on.