Comment by daxfohl

1 day ago

Couldn't you make lazily evaluated code in erlang too, even if it's not lazy by default like Haskell? You'd just need function pointers, right? Or is that not enough?

Haskell can have circular references because its laziness is implemented with thunks, which have a mutable cell in which to store the computed value so that terms don't get evaluated more than once. Here's a Haskell function that makes a circular linked list:

    -- circular linked list with one item
    repeat x = let xs = x:xs in xs

Here's a rough equivalent in JavaScript that doesn't use thunks, just functions:

    function repeat(x) {
        function xs() {
            return [x, xs]; // [first, rest]
        }
        return xs;
    }

The Haskell version has a cycle because, after evaluation, `repeat x` will be a circular linked list, but all the "lists" we create in the JavaScript code above are just the closure `xs`.

For completeness, here's a JavaScript version that uses thunks:

    class Thunk {
        constructor(f) { this.f = f; }
        get() { if (this.f) { this.v = (this.f)(); delete this.f; } return this.v; }
    }

    function repeat(x) {
        let xs = new Thunk(() => {
            return [x, xs]; // [first, rest]
        });
        return xs;
    }

If you try calling `x = repeat(1); x.get()`, you can see that we get a circular list.