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 let-bound ‘left’. The
‘t’ in the let-binding 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_tasks-1 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_tasks-2] WHILE TASK middles ASYNCHRONOUSLY SENDS A 10 BYTE MESSAGE TO TASK ends SUCH THAT ends IS NOT IN [1, num_tasks-2] 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 variable-binding, 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_tasks-1’.
Hence, the following coNCePTuaL statement will always output values
less than or equal to ‘num_tasks-1’ (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]