## Lazy Realization

January 2, 2016

Support for using `realized?` with lazy sequences has landed in ClojureScript.

What kind of new fun can we have with this capability? # Fun

First, let's say we have a lazy sequence. Here's one representing the factors for each natural number:

``````(def factors
(map (fn [n]
(filter (fn [x]
(zero? (rem n x)))
(range 1 (inc n))))
(rest (range))))
``````

This sequence looks like

``````((1) (1 2) (1 3) (1 2 4) (1 5) ...)
``````

Even though the `def` defines an infinite sequence, defining it at the REPL simply results in the var `#'factors` being returned, but with none of the factors yet being calculated.

You can verify this: `(realized? factors)` yields `false`.

If you evaluate `(first factors)`, you will get `(1)`. After doing this, `(realized? factors)` will yield `true` which means that the first item has been realized. And you can confirm that only the first item has been realized: `(realized? (rest factors))` yields `false`.

Now, let's say we do something like, `(take 4 factors)`, causing the next 3 items of this infinite sequence to be calculated and cached. A function like the following (due to Alan Malloy) can be used to calculate how much of the infinite sequence has been realized:

``````(defn realized-length [xs]
(loop [n 0 xs xs]
(if (realized? xs)
(recur (inc n) (rest xs))
n)))
``````

With this, `(realized-length factors)` produces the desired result of `4`.

# Implementation

Adding support for `realized?` for lazy sequences was relatively easy in ClojureScript. At its core, `realized?` simply needs its argument to be of a type that satisfies `cljs.core/IPending`. This involves providing an implementation for its `-realized?` method.

In ClojureScript, lazy sequences are implemented by a `LazySeq` `deftype` with a `fn` field which is used to realize the value. After this `fn` has been used, it is set to `nil` (it is marked as `^:mutable`), and, via this side effect, we can deduce that the value has been realized.

This strategy is in fact analogous to the one used in `Delay`—the type that underlies the `delay` function—and its existing support for `realized?` in ClojureScript.

The implementation landed for `realized?` for `LazySeq` simply mimics the approach used for `Delay`, checking to see if the `fn` mutable field has been set to `nil` in the inline `IPending` implementation in the `LazySeq` `deftype`:

``````IPending
(-realized? [x]
(not fn))
``````

That's all there is to it!

Tags: ClojureScript