liveBook · Manning

By-name parameter

As explained in Functional Programming in Scala, Second Edition

A by-name parameter is a Scala parameter whose argument expression is evaluated when the parameter is accessed rather than when the function is invoked.

A by-name parameter accepts an argument expression without evaluating it at the call. In Scala, write `=> A` before the parameter type. The expression is evaluated only when the parameter name is used in the function body, making that parameter nonstrict. section 5.1 section 5.6

This differs from passing an ordinary value: a strict parameter is evaluated before the function runs. It also differs from explicitly passing `() => A`: that form exposes a thunk which must be called with `()`, whereas `=> A` lets the body refer to the parameter normally. section 5.1

def if2[A](cond: Boolean, onTrue: => A, onFalse: => A): A =
  if cond then onTrue else onFalse

A conditional can defer both result branches. Only the branch selected by `cond` is referenced, so an error in the other branch is never evaluated. section 5.1

Repeated access repeats work

By-name does not cache an argument automatically. If `maybeTwice` uses `i + i`, the supplied expression runs twice; if the condition is false, it is not run at all. Put the parameter in a `lazy val` when repeated references should share one computed result. section 5.1

By-name parameters help separate a computation from the decision to demand it. A `LazyList` smart constructor uses them for its head and tail, then memoizes each with `lazy val`, preserving deferred evaluation while avoiding repeated expensive work after forcing. section 5.2 section 5.2.1

Use a by-name parameter when a function needs control over whether and when an argument runs:

  • Select one of several branches, as with a conditional or short-circuiting operation. section 5.1 section 5.6
  • Delay construction of appended lazy-list data until the original list has been traversed. section 5.6
  • Combine deferred computation with `lazy val` when it may be forced more than once but should run once. section 5.1 section 5.2.1

Deferred append

`append` takes its second `LazyList` as `that: => LazyList[A2]` and starts a right fold with it. Since the fold may not need that accumulator immediately, the appended list remains uncomputed until demand reaches it. section 5.6

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Explains thunk expansion, demand timing, repeated evaluation, and lazy-val caching rather than treating syntax alone as the mechanism.
Examples
Uses a custom conditional, `maybeTwice`, a memoized variant, and `LazyList.append` to show deferred and repeated evaluation.
What it assumes
Builds from zero by contrasting ordinary arguments with zero-argument functions before introducing `=> A` syntax.
What you can do after
Apply it via Scala by-name parameters to defer selected computations and add lazy-value caching when repeated forcing must not recompute.
How it connects
Connects nonstrictness with thunks, lazy values, memoization, LazyList, foldRight, and short-circuiting operators.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.