It often happens that one wants to change just one particular slot of a list or string, which is stored in a variable or a property. This can be done conveniently using an indexed assignment having one of the following forms:
variable[index-expr] = result-expr object-expr.name[index-expr] = result-expr object-expr.(name-expr)[index-expr] = result-expr $name[index-expr] = result-expr
The first form writes into a variable, and the last three forms write into a
property. The usual errors (E_TYPE
, E_INVIND
, E_PROPNF
and E_PERM
for lack of read/write permission on the property) may be
raised, just as in reading and writing any object property; see the
discussion of object property expressions below for details. Correspondingly,
if variable does not yet have a value (i.e., it has never been assigned
to), E_VARNF
will be raised.
If index-expr is not an integer, or if the value of variable or the
property is not a list or string, E_TYPE
is raised. If
result-expr is a string, but not of length 1, E_INVARG
is
raised. Now suppose index-expr evaluates to an integer k. If
k is outside the range of the list or string (i.e. smaller than 1 or
greater than the length of the list or string), E_RANGE
is raised.
Otherwise, the actual assignment takes place. For lists, the variable or the
property is assigned a new list that is identical to the original one except at
the k-th position, where the new list contains the result of
result-expr instead. For strings, the variable or the property is
assigned a new string that is identical to the original one, except the
k-th character is changed to be result-expr.
The assignment expression itself returns the value of result-expr. For
the following examples, assume that l
initially contains the list
{1, 2, 3}
and that s
initially contains the string "foobar":
l[5] = 3 error--> E_RANGE l["first"] = 4 error--> E_TYPE s[3] = "baz" error--> E_INVARG l[2] = l[2] + 3 => 5 l => {1, 5, 3} l[2] = "foo" => "foo" l => {1, "foo", 3} s[2] = "u" => "u" s => "fuobar" s[$] = "z" => "z" s => "fuobaz"
Note that the $
expression may also be used in indexed assignments with
the same meaning as before.
Fine point: After an indexed assignment, the variable or property contains a new list or string, a copy of the original list in all but the k-th place, where it contains a new value. In programming-language jargon, the original list is not mutated, and there is no aliasing. (Indeed, no MOO value is mutable and no aliasing ever occurs.)
In the list case, indexed assignment can be nested to many levels, to work on
nested lists. Assume that l
initially contains the list
{{1, 2, 3}, {4, 5, 6}, "foo"}
in the following examples:
l[7] = 4 error--> E_RANGE l[1][8] = 35 error--> E_RANGE l[3][2] = 7 error--> E_TYPE l[1][1][1] = 3 error--> E_TYPE l[2][2] = -l[2][2] => -5 l => {{1, 2, 3}, {4, -5, 6}, "foo"} l[2] = "bar" => "bar" l => {{1, 2, 3}, "bar", "foo"} l[2][$] = "z" => "z" l => {{1, 2, 3}, "baz", "foo"}
The first two examples raise E_RANGE
because 7 is out of the range of
l
and 8 is out of the range of l[1]
. The next two examples
raise E_TYPE
because l[3]
and l[1][1]
are not lists.