I have some code that uses list comprehensions in elixir and performs some long operations. I need this code to be lazily evaluated instead of running immediately (eager evaluation).
Imagine I have a list comprehension like the following:
for a <- long_operation(), b <- longer_operation() do a + b end
b will be eagerly evaluated, so as to return
a + b. However, both
longer_operation() take a very long time to run (as the name implies) and I will only absolutely run them if I have to.
I want to come up with a solution that allows for my code to be lazily evaluated. Say, for example, to have a data structure or some other construct where I can then call
run() to actually do the hard work.
My first idea was to just put everything inside of anonymous functions:
for a <- fn -> long_operation() end, b <- fn -> longer_operation() end do a + b end
This worked as well as you would expect, i.e., it didn’t. The main reason being: “You cannot sum two functions”.
And it makes sense.
My next option is then to have a data-structure hold the values of these computations, and have the list comprehension return said data-structure.
I would then call
run() or something similar, and then the operation would be executed.
You can probably think of this as the
IO construct in languages like Scala or Haskell (pardon for the poor comparison).
Other people have suggested the use of
GenServers to achieve this, but this avenue does not sit well with me for two main reasons:
- I am adding a runtime dependency to a code that should not even know
GenServers exist in the first place.
- Also I fail to see how this would help in any way.
The issue here is that I believe this will force me to implement a mini AST with the instructions of what needs to be executed when I call
run(). Not only do I lack the knowledge to do this, It also sounds overkill at first glance.
Surely, Elixir has a way to have expressions being lazily evaluated that I am not aware of.
So this brings me to the question:
- What mechanisms does Elixir use to have lazy evaluation?
- Are there any data-structures/libraries out there that do this? (lazy evaluation)
Please let me know!