Lazy vs Eager loading

Eager

When we are eager loading - all operations need to execute before completion

Example:

Enum.map(1..10_000_000, fn(x) -> x * x end)

What would happen in the above example? How might this be a problem?

Lazy

Operations are performed only at the last minute

Instead of peforming the operations, it returns a precomputed function.

Lets look at an example and figure out what is happening below

Stream.cycle([1, 2, 3])
#Function<59.87278901/2 in Stream.unfold/2>
Stream.cycle([1, 2, 3]) |> Stream.take(10) |> Enum.to_list

Streams are composable, lazy enumerables. A stream is any enumerable that generates items one by one.

Stream.cycle/1 will create a stream that will cycle through a given enumerable infinitely.

Notice how the following function returns a stream.

Stream.cycle([1, 2, 3])
#Function<59.87278901/2 in Stream.unfold/2>

Now looking at Stream.take, take(enum, count) - takes an enumerable and a count as arguments. It lazily takes the numbers of items from the enumerable equal to the count, and stops the enumeration.

In this case

Stream.cycle([1, 2, 3])
#Function<59.87278901/2 in Stream.unfold/2>
Stream.cycle([1, 2, 3]) |> Stream.take(10) |> Enum.to_list

It the stream would take the first 10 items.

Enum.to_list will convert an enumerable to a list.

If we took out the take function and just had the following -

Stream.cycle([1, 2, 3]) |> Enum.to_list

Why would this be a problem?

Hint: Stream.cycle will run infinitely.