Next: Conditional execution, Previous: Iterating, Up: Complex statements [Contents][Index]
There are four ways to bind a value to a variable:
LET
keyword (this section)The LET
statement has the following form:
LET
<let_binding> 

[ AND
<let_binding>]* 

WHILE <simple_stmt> 
where <let_binding> is defined as follows:
<let_binding>  ::= 
<ident>
BE 
expr  
  <source_task>  
 
A RANDOM TASK [
<random_task_constraints>] 
The optional
<random_task_constraints> limits the set of tasks
from which A RANDOM TASK
selects:
<random_task_constraints>  ::= 
OTHER THAN <expr> 
  LESS
THAN
<expr> [ BUT NOT <expr>] 

 
GREATER THAN <expr> [ BUT NOT
<expr>] 

  IN
‘[’ <expr>
‘,’ <expr>
‘]’ [ BUT NOT <expr>] 
An
<ident> bound using the form ‘ LET
<ident>
BE
<source_task>’ represents a group of
tasks and must therefore be accessed using the TASK
GROUP
construct (see Source tasks). For example, in
the coNCePTuaL program
LET left BE TASKS t SUCH THAT t < num_tasks/2 WHILE TASK GROUP left SENDS A 1 KILOBYTE MESSAGE TO TASK num_tasks  left  1
the ‘ TASK GROUP
left’ expression defines
‘left’ as the group of tasks described by
‘
TASKS
t SUCH THAT
t <
num_tasks/2’. The ‘left’ in
‘num_tasks  left  1’ refers back to
that definition of ‘left’, not
the letbound ‘left’. The
‘t’ in the letbinding is used only to
specify the group of tasks that will be bound to
‘left’. Its scope is limited to the
expression ‘t < num_tasks/2’. In other
words, the preceding example is equivalent to
TASKS left SUCH THAT left < num_tasks/2 SEND A 1 KILOBYTE MESSAGE TO TASK num_tasks  left  1
The advantage of using LET
to define a task group is that
the same—possible complex—description of a set of tasks
can be reused in multiple statements without having to type it
repeatedly.
Here are some further examples of LET
:
LET reps BE 3 WHILE FOR reps REPETITIONS TASK 0 OUTPUTS "Laissez les bons temps rouler." LET src BE num_tasks1 AND dest BE num_tasks/2 WHILE TASK src SENDS A 55E6 BIT MESSAGE TO TASK dst LET hotspot BE A RANDOM TASK WHILE TASKS other SUCH THAT other<>hotspot SEND 1000 1 MEGABYTE MESSAGES TO TASK hotspot LET target BE A RANDOM TASK OTHER THAN 3 WHILE TASK 3 SENDS A 24 BYTE MESSAGE TO TASK target LET x BE A RANDOM TASK AND y be a RANDOM TASK GREATER THAN x WHILE TASK 0 OUTPUTS "Did you know that " AND x AND " is less than " AND y AND "?" LET nonzero BE A RANDOM TASK LESS THAN 10 BUT NOT 0 WHILE TASK nonzero SLEEPS FOR 2 SECONDS LET middles BE A RANDOM TASK IN [1, num_tasks2] WHILE TASK middles ASYNCHRONOUSLY SENDS A 10 BYTE MESSAGE TO TASK ends SUCH THAT ends IS NOT IN [1, num_tasks2] LET num BE 1000 AND num BE num*2 WHILE TASK 0 OUTPUTS num  2000
That last example demonstrates that LET
can bind a variable to a
function of its previous value. It is important to remember,
though, that variables in coNCePTuaL cannot be assigned, only bound
to a value for the duration of the current scope. They can,
however, be bound to a different value for the duration of a child
scope. The following example is an attempt to clarify the
distinction between binding and assignment:
LET var BE 123 WHILE FOR 5 REPETITIONS LET var BE var+1 WHILE TASK 0 OUTPUTS var  124  124  124  124  124
In that example, ‘var’ is bound to
‘123’ for the scope containing the
FOR
statement. Then, within the FOR
statement, a new scope begins
with ‘var’ being given one plus the value
it had in the outer scope, resulting in
‘124’. If coNCePTuaL supported assignment
instead of variablebinding, the program would have output
‘124’, ‘125’,
‘126’, ‘127’, and
‘128’. Note that if A
RANDOM TASK
were used in the example instead of
‘var+1’, ‘var’
would get a different value in each iteration.
When a variable is
LET
bound to A RANDOM TASK
, all tasks
agree on the random number. Otherwise, task A might send
a message to task B but task B might be
expecting to receive the message from task C, thereby
leading to a variety of problems. If there are no valid random
tasks, as in the following example, A RANDOM TASK
will
return ‘1’:
LET invalid_task BE A RANDOM TASK GREATER THAN num_tasks WHILE TASK 0 OUTPUTS invalid_task  1
Furthermore, the
<expr> passed to GREATER THAN
is bounded
from below by ‘0’ and the <expr>
passed to
LESS THAN
is bounded from above by
‘num_tasks1’. Hence, the following
coNCePTuaL statement will always output values less than or equal
to ‘num_tasks1’ (unless
num_tasks
is greater than 1*10^6, of course,
in which case it will always output values less than
1*10^6):
LET valid_task BE A RANDOM TASK LESS THAN 1E6 WHILE TASK valid_task OUTPUTS "Hello from " AND valid_task
Next: Conditional execution, Previous: Iterating, Up: Complex statements [Contents][Index]