< Back to IRCAM Forum

Assignment (and Evaluation) of Values

Hi JLG, @giavitto and anybody else who may be interested: I accidently posted a topic regarding Antescofo in Uncategorized: Assignment of Values. Sorry for the error, Kai Yves

Hello Kyl.

The short answer: you should use local variables to avoid interference between forall iteration.

The long answer: Your original program is

forall $i in 3 {
	let $receiver := "OneOfTwo"+(($i%2)+1)
	print intended receiver ($receiver)
	($somedelay)ms @command($receiver) dosomething
	print invoked receiver ($receiver)
	let $somedelay := @rand(100)
}

and you expect to have at two messages invoked receiver OneOfTwo1 and one message invoked receiver OneOfTwo1, which is not the case. For instance, you may have:

intended receiver OneOfTwo1
invoked receiver OneOfTwo1
intended receiver OneOfTwo2
intended receiver OneOfTwo1
invoked receiver OneOfTwo1
invoked receiver OneOfTwo1

The problem is not coming from the evaluation time of expressions. Indeed, the expression in the right hand side of an assignment is evaluated when the assignment is performed, as you would expect.

BUT the variable $receiver is a global variable. The forall body instances (one per indice $i) are evaluated in the same instant. At the end of these evaluation, $receiver's value is "OneOfTwo1" because the body’s instances are evaluated in the same instant but in the order of increasing indices. So the last evaluated index is 2 and (2%2) + 1 returns 1. So, when the delays ($somedelay)ms have elapsed, the messages print invoked receiver ($receiver) are all sent with this value of the receiver.

A similar problem occurs for the delay ($somedelay)ms (only slightly more complicated because the value of the delay determines if there are interferences or not between instances).

The solution is simple: use a local variable that exists (and is accessible) only for each instance of the forall body:

forall $i in 3 {
	@local
         $receiver := "OneOfTwo"+(($i%2)+1),
	     $somedelay := @rand(100)

	print intended receiver ($receiver)

	($somedelay)ms @command($receiver) dosomething
	print invoked receiver ($receiver)
}

 

As a side note, interference between concurrent actions that share variables lead to subtle bugs. They are not always perceptible: their value is not the intended value but a viable one. So often there is no error message.
Contrary to most programming language, there is no need of semaphore, synchronization barrier or atomic data operation in Antescofo for the concurrent accesses of data. By construction, each instantaneous sequence of actions that takes place in the same instant (i.e., there is no delay in the sequence), are performed atomically without interruption and all such sequences are evaluated in a deterministic sequential order. However, this does not prevent mistakes such the previous one.

Thank you, @giavitto, for the answer. So, in Antescofo one cannot be local enough, :wink: . In the given example, the variable must be local to the loop. In the code from which I extracted the example, $receiver is declared local in the group which encloses the loop, but that’s not local enough. Your explanation makes that clear and comprehensible.