411 REFERENCE · Wikibooks
The Sway Reference Manual/Assignment
Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.
Once a variable has been declared, it is possible to change its binding
using the assignment operator. Consider the following interaction with
the interpreter:
sway> var BLACK = 1; //initialization!
INTEGER: 1
sway> var BROWN = 2;
INTEGER: 2
sway> var GREEN = 3;
INTEGER: 3
sway> var eyeColor = BLACK;
INTEGER: 1
sway> eyeColor;
INTEGER: 1
sway> eyeColor = GREEN; //assignment!
INTEGER: 3
sway> eyeColor == BROWN; //equality?
SYMBOL: :false
sway> eyeColor == GREEN;
SYMBOL: :true
The operator/variable = (equals sign) is bound to the assignment function.
The assignment function, however, is not a true function, like those bound
to + and *. Recall that + and the like evaluate the things on either
side (recall that those things on either side are generically known as
operands) before combining them. For =, the left operand is not evaluated
(if it were, the assignment
eyeColor = GREEN
would attempt to change the
meaning of 1 to be 3). In general, an operator which does not evaluate
all its arguments is known as a special formUnlike most languages, Sway allows user defined special forms..
Now we can see a variable definition has two steps. In the first step,
the variable is created and in the second step, a value is assigned to
that variable.
The last two expressions given to the interpreter in the previous
interaction refer to the == (equality) operator.
The operator == returns
true if its operands refer to the same thing and false otherwise. In the
interaction above, the variables BLACK, GREEN, and BROWN are not meant
to change from their initial values.
We denote variables whose values aren't supposed to change
by naming the
variable using (mostly) capital letters (this convention is borrowed
from earlier programming languages).
The use of caps emphasizes the constant nature of the (not too) variable.
In the above interaction with the interpreter, we use the integers 1, 2,
and 3 to represent the colors black, brown, and green. By abstracting 1,
2, and 3 and giving them meaningful names (i.e., BLACK, BROWN,
and GREEN) we find it easy to read code that
assigns and tests eye color.
We do this because it is difficult to remember which integer
is assigned to which color. Without the variables BLACK, BROWN, and
GREEN, we have to keep little notes somewhere to remind ourselves what's
what. Here is an equivalent interaction with the interpreter without
the use of the variables BLACK, GREEN, and BROWN.
sway> var eyeColor = 1;
INTEGER: 1
sway> eyeColor;
INTEGER: 1
sway> eyeColor = 3;
INTEGER: 3
sway> eyeColor == 2;
SYMBOL: :false
sway> eyeColor == 3;
SYMBOL: :true
In this interaction, the meaning of the test eyeColor == 3 is not so obvious.
Another approach to constants is to use symbols.
Since Sway has symbols as primitives, we can dispense with the constant-like variables and the integers altogether:
sway> var eyeColor = :black;
SYMBOL: :black
sway> eyeColor;
SYMBOL: :black
sway> eyeColor = :green;
SYMBOL: :green
sway> eyeColor == :brown;
SYMBOL: :false
sway> eyeColor == :green;
SYMBOL: :true
sway> println("eye color is ",eyeColor);
eye color is green
SYMBOL: :green
Note how much more readable this version of the interaction is.
Also note that symbols, when printed, are printed without
the colon.
Precedence and Associativity of Assignment
Assignment has the lowest precedence among the binary operators. It is
also right associative. The right associativity allows for statements like
a = b = c = d = 0;
which conveniently assigns a zero to four variables at once and is
equivalent to:
(a = (b = (c = (d = 0))));
because of the right associative nature of the operator. Since the
resulting value of the assignment operation is the value assigned,
this statement works as desired.
How it works
Sway takes a novel approach to assignment.
Every time a value is retrieved,
its address is (usually) saved in an internal register.
The assignment operator
takes advantage of this fact by:
looking up the value of the left-hand-side
checking for a valid address in the internal register
writing the value of the right hand side to the valid address
For example, the assignment
x = 3;
proceeds by looking up the value of x. The current value of
x is ignored, but the internal register now contains the location
of x.
The value of 3 is then copied to the address and
x has a new value.
By this method, one can write to array and list elements as well
as objects:
a[y] = z;
head(tail(items)) = :green;
a . f() . b = "hello";
There are some limitations to assignment. For example, you
cannot use the assignment operator to change the tail of
a list. For example, this attempt will fail:
tail(items) = list(a,b,c);
because the tail of a list does not have not a normal address in Sway.
To change the tail of the list, one uses the tail= operator, instead:
items tail= list(a,b,c);
or
tail=(items,list(a,b,c));
if you prefer function call syntax.
There is a head= operator for changing the
head of the list, but it is bound to the
regular assignment operator, so you can use
either.
Assigning to Thunks
If the code in a thunk has a regular Sway address, you can
use the assignment operator to update the value at that
address. This is how a forEach function would work:
function forEach($target,items,$body)
{
while (items != null)
{
$target = head(items);
force($body);
items = tail(items);
}
}
Here, the thunk $target is repeatedly updated with the (new)
head of the list. Once the update is made with the assignment
operator, the body of the forEach is forced and the process repeated.
The forEach function can be called with a simple variable, as in
var i;
forEach(i,range(0,4))
{
println("i is ",i);
}
or with an array or list location, as in
var i = array(1,2,3);
forEach(i[2],range(0,4))
{
println("i[2] is ",i[2]);
}
or with an object member, as in
function bundle(a,b) { this; }
var i = bundle(1,2);
forEach(i . a,range(0,4))
{
println("i . a is ",i . a);
}
Footnotes
Variables and Environments Functions