Variables

Antescofo variables are imperative variables: they are like a box that holds a value. The assignment of a variable consists of changing the value stored in the box:

          $v := expr
          let $v := expr

The two forms are equivalent, but the let keyword is sometimes mandatory, see below.

An assignment is an action and like other actions, it can be done after a delay. We stress that variable assignments are actions and not expressions. However, they are instantaneous and they can appear in extended expressions in the body of a function.

Variables are named with a $-identifier. By default, a variable is global - that is, it can be referred to in an expression anywhere in a score.

Note that variables are not typed: the same variable may hold and integer and later a string, for example.

User variables are assigned within an augmented score using Assignment Actions, see assignment. However, they can also be assigned by the external environment, using a dedicated API:

Also see the section accessing scoped variable below.

Histories: Accessing the Past Values of a Variable

Variables are managed in an imperative manner. The assignment of a variable is seen as an internal event that occurs at some date. Such event is associated to a logical instant. Each variable has a time-stamped history. So, the value of a variable at a given date can be recovered from the history, achieving the notion of stream of values. Thus, $v corresponds to the last value (or the current value) of the stream. It is possible to access the value of a variable at some date in the past using the dated access:

          [date]:$v

returns the value of variable $v at date date. The date can be expressed in three different ways:

For each variable, the programmer may specify the size n of its history variable declaration. So, only the n “last values” of the variable are recorded. Accessing the value of a variable beyond the recorded values returns an undefined value.

Dates functions

Two functions let the composer to know the date of a logical instant associated to the assignment of a variable:

      @date([n#]:$v)

returns the date in absolute time of the nth to the last assignement of and

      @rdate([n#]:$v)

returns the date in relative time (relative to the musician).

These forms mimic the form of functions but they are not; they are special forms and only accept a variable or the dated access to a variable.

Variable Declaration

Variables are global by default, that is, visible everywhere in the score, or they are declared local to a sequence of actions which limits its scope and puts a constraint on its lifetime.

For instance, the scope of a variable declared local in a loop body is restricted to one instance of the loop body, so two loop bodies refer to two different instances of the local variable. This is also the case for the body of a whenever or of a process.

Local Variables

To make a variable local to a scope, it must be explicitly declared using a @local declaration. A scope is introduced for the body of each compound action. The declaration, may appear everywhere in the scope and takes a comma separated list of variables:

          @local $a, $i, $j, $k

There can be several declarations in the same scope and all local variables can be accessed from the beginning of the scope, regardless of the location of their declaration.

A local variable may hide a global variable and there is no warning if it does. A local variable can be accessed only within its scope. For instance

          $x := 1
          group {
              @local $x
              $x := 2
              print "local var $x: " $x
          }
          print "global var $x: " $x

will print

      local var $x: 2
      global var $x: 1

Lifetime of a Variable

A local variable can be referred as soon as its nearest enclosing scope is started but it can persist beyond the enclosing scope lifetime. For instance, consider this example :

          Group G
          {
              @local $x
              2 Loop L
                {
                     ... $x ...
                }
          }

The loop ::antescofo L nested in the group runs forever and accesses the local variable after “the end” of the group G (the group ends whith the launch of its last action, see Action Sequence). This use of $x is perfectly legal. Antescofo manages variables efficiently and the memory allocated for $x persists as long as needed by the children of G but no more.

History Length of a Variable

For each variable, Antescofo only records a history of limited size. This size is predetermined, when the score is loaded, as the maximum of the history sizes that appears statically in expressions and in variable declarations.

In a declaration, the specification of a history size for the variable takes the form:

          n:$v

where n is an integer. This syntax specifies that variable has an history of length at least n.

To make it possible to specify the size of global variable's history, there is a declaration @global

          @global  $x, 100:$y

similar to the declaration @local. Global variable declarations may appear anywhere an action may appear. Variables are global by default, thus, the sole purpose of a global declaration, beside documentation, is to specify history lengths.

The occurence of a variable in an expression is also used to determine the length of its history. In an expression, the nth past value of a variable $v is accessed using the dated access construction (see above):

          [n#]:$v

When n is a constant integer, the length of the history is assumed to be at least n.

When there is no declaration and no dated access with constant integers, the history size has an implementation dependant default size.

The special form @history_length($x) returns the length of the history of the variable $x.

History reflected in a Map or in a Tab

The history of a variable may be accessed also through a map or a tab. Three special functions are used to build a map (resp. a tab) from the history of a variable:

These six functions are special forms: they only accept a variable as an argument. These functions build a snapshot of the history at the time they are called. Later, the same call will eventually build different maps and tabs. Beware that the history of a variable is managed as a ring buffer: when the buffer is full, any new update takes the place of the oldest value.

Plotting the history of a variable

The history of a variable can be plotted in absolute or in relative time using the command @plot and @rplot. These two functions are special forms accepting only a list of variables as arguments. They return true if the plot succeeded and false elsewhere.

If there is only one argument $x , the referred values can be a tab (of numeric values) and each element in the history of the tab is plotted as a time series on the same window. If they are more than one argument, each variable must refer to a numeric value and the time series of the variables values are plotted on the same window.

Note that only the values stored in the history are plotted : so usually one has to specify the length of the history to record, using a @global or @local declaration.

The @plot and @rplot special forms expand to a call to the function gnuplot1. For example, the expression expands into

          @gnuplot( "$x", @history_tab_date($x), @history_tab($x), 
                    "$y", @history_tab_date($y), @history_tab($y) )

See description of @gnuplot in Library Functions.

Accessing a Local Variable “From Outside its Scope of Definition”

A local variable can be accessed in its scope of definition, or from one of its child scopes, using its identifier. It is possible to access the variable from “outside its scope” using the dot notation through an exec. Here, “outside” means “not in the scope of definition nor in one of its children”. Beware that accessing a local variable from outside its definition scope:

If the scope of definition of the variable is not alive at the time of the access, an undefined value is returned and an error is signaled. Else, if there is no variable with this identifier locally defined in the scope, then the variable is looked up in the enclosing scope. The process is iterated until the top-level is reached. At this point, if there is no global variable with the specified identifier, an undefined value is returned and an error is signaled.

The Dot Notation

To access the variable defined in one specific instance of a group, or more generally of a compound action introducing a scope (@whenever, loop, process call, etc.), one must use the dot notation through the exec referring to this instance. Exec are introduced in section Exec.

It is possible to read the value of a local variable through the dot notation:

          $p := ::P()
          $x_of_p := $p.$x 

Expression $p.$x get the value of the local variable $x in the process ::P launched at the previous line. The instance of the process is accessed trough its exec, see section Exe.

The expression at the left of the dot operator may be more complex than just a variable:

          $p := [ ::P() | (10) ]
          $x_of_p2 := $p[2].$x

The first line launch 10 instances of process ::P using a tab comprehension. The second line get the local variable of the third instance of ::P.

Assigning a Variable From Outside its Scope

As previously mentionned, a variable can be assigned from “outside”, see:

The OSCreceive and the setvar command can be used only for global variable. But local variable can be the target of the two other mechanisms.

The assignment of a local variable through the dot notation is similar to an usual assignment:

          $p := ::P()
          let $p.$x := 33 // assign the local variable $x in the process ::P

The expression at the left of the dot operator may be more complex than just a variable:

          $p := [ ::P() | (10) ]
          let $p[2].$x := 33

The first line launches 10 instances of process ::P. The second line sets the local variable of the third instance of ::P.

Notice the let keyword: it is needed in an assignment when the expression in the left hand side of the assignment is more complex than a variable.

These assignments are monitored by the whenever where the local variable $x appears. But an expression $p.$x does not monitor the local variable of the process. See section Reference to a scoped variable

Antescofo System Variables

System variables are internal variables managed directly by Antescofo and are updated automatically by the system. They are useful for interacting with, for example, the machine listener during performances and creating interactive setups.

The following variables are managed as ordinary variables:

Note that when an event occurs, several system variables are likely to change simultaneously. Notice that, as for all variables, they are case-sensitive.

Special Variables

These variables are similar to system variables, but they cannot be watched by a whenever:

Variables and Notifications

In Antescofo, a set of entities to be notified is associated to each variable. The notification mechanism is the core device used by the reactive engine to implement the computations.

Notification of events from the machine listening module drops down to the more general case of variable-change notification from an external environment. Actions associated to a musical event are notified through the variable $BEAT_POS. This is also the case for the group, loop and curve constructions which need the current position in the score to launch their actions with @loose synchronization strategy. The whenever construction is notified by all the variables that appear in its condition. The scheduler must also be globally notified upon any update of the tempo computed by the listening module and on the update of variables appearing in the local tempi expressions.

Temporal Shortcuts. The notification of a variable change may trigger a computation that may end, directly or indirectly, in the assignment of the same variable. This is known as a “temporal shortcut” or a “non causal” computation. The reactive engine takes care of stopping the propagation when a cycle is detected. See section Causal Score and Temporal Shortcuts.



The next section temporal variables investigates the use of a variable to track a process and to infer a tempo. Then we take a look at


  1. The gnuplot program is a portable command-line driven graphing utility for Linux, MS Windows, Mac OSX, and many other platforms. Cf. www.gnuplot.info. It must be installed on the system to have a working @gnuplot function.