2. evaltime and runtime

Execution in alv is split into two phases - evaltime and runtime.

At evaltime, that is whenever there is change to the source code, alv behaves similar to a Lisp. But once one such eval cycle has executed, runtime starts, and alv behaves like a dataflow system like PureData, Max/MSP or vvvv.

Every alive expression returns a stream of values. Whenever an input to an operator changes, the operator (may) update and respond with a change to its output as well. To see this in action, we need to start with a changing value. Number literals like 1 and 2, are evaltime constant, which means simply that they will never update. Since all inputs to our math/+ operator are evaltime constant, the result is constant as well. To get some runtime activity, we have to introduce a side-effect input from somewhere outside the system.

The time module contains a number of operators whose outputs update over time. Lets take a look at time/tick:

(import* time)
(trace (tick 1))

This will print a series of numbers, incrementing by 1 every second. The parameter to time/tick controls how quickly it counts - try changing it to 0.5 or 2. As you can see, we can change time/tick while it is running, but it doesn't lose track of where it was!

All of the other things we learned above apply to streams of values as well - we can use def to store them in the scope, transform them using the ops from the math module and so on:

(import* time math)
(def tik (tick 0.25))
(trace (/ tik 4))

Note that if you leave the time/tick's tag in place when you move it into the def expression, it will keep on running steadily even then.