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]