Description
In this section we'll discuss simple local assignment to variables, multiple local assignment, and installation and use of method functions. See also the operator =, which handles other forms of assignment, as well as the operator <-, which is an assignment operator that evaluates its left hand side and can have assignment methods installed for it by the user.
simple local assignment
-
- Usage:
x := e
-
Inputs:
-
Outputs:
-
a thing, the value of the expression is e
-
Consequences:
-
a new local variable x is created. The scope of x is the innermost current function body or for loop, or the current file.
-
e is assigned to x, so future references to the value of x yield e
-
a warning message is issued if a local variable with the same name has already been created
i1 : x
o1 = x
o1 : Symbol
|
i2 : x := 4
o2 = 4
|
i3 : x
o3 = 4
|
In the next example, we see that the scope of the local variable p is limited to the body of the function.
i4 : g = () -> ( p := 444; p )
o4 = g
o4 : FunctionClosure
|
i5 : g()
o5 = 444
|
i6 : p
o6 = p
o6 : Symbol
|
In this example, we see that the scope of the local variable j is limited to the body of a for loop.
i7 : i="a b c";
|
i8 : for i to 3 list j := i+1
o8 = {1, 2, 3, 4}
o8 : List
|
i9 : i
o9 = a b c
|
i10 : j
o10 = j
o10 : Symbol
|
In this example, we see that a function returned by another function retains access to the values of local variables in its scope.
i11 : g = () -> ( p := 444; () -> p )
o11 = g
o11 : FunctionClosure
|
i12 : g()
o12 = FunctionClosure[stdio:11:22-11:29]
o12 : FunctionClosure
|
i13 : oo ()
o13 = 444
|
Functions returned by a function can also modify local variables within their scope, thereby communicating with each other.
i14 : g = () -> ( p := 444; (() -> p, i -> p = i))
o14 = g
o14 : FunctionClosure
|
i15 : (b,c) = g()
o15 = (b, c)
o15 : Sequence
|
i16 : b()
o16 = 444
|
i17 : c 555
o17 = 555
|
i18 : b()
o18 = 555
|
Since the value of the entire expression is e, and since the operator = is right-associative (see precedence of operators), e can be easily assigned to more than one variable, as in the following example.
i19 : a := b := 44
o19 = 44
|
i20 : a
o20 = 44
|
i21 : b
o21 = 44
|
By the way, there is a difference between a variable (to which values can be assigned) and a symbol (which can be used as an indeterminate in making a polynomial ring). If you want a local variable to which is assigned the corresponding local symbol, then combine the use of := with the use of local, as in the following example, which illustrates a good way to do a computation in a temporary ring without disturbing the values of any global variables.
i22 : g = () -> (
x := local x;
R := QQ[x];
(x+2)^10);
|
i23 : g()
10 9 8 7 6 5 4 3
o23 = x + 20x + 180x + 960x + 3360x + 8064x + 13440x + 15360x +
-----------------------------------------------------------------------
2
11520x + 5120x + 1024
o23 : QQ[x]
|
multiple local assignment
-
- Usage:
(x,y,z,...) := (c,d,e,...)
-
Inputs:
-
Outputs:
-
the value of the expression is (c,d,e,...)
-
Consequences:
-
new local variables x, y, z, ... are created
-
the expressions c,d,e,... are assigned to the variables x,y,z,..., respectively, as above.
-
If the left hand side has more elements than the right hand side, then the extra symbols on the left side are given the value null.
-
If the left hand side has fewer elements than the right hand side, then the last symbol on the left hand side is given as value a sequence containing the trailing elements of the right hand side.
-
If the right hand side is not a sequence, then it is assigned to the first symbol on the left, and the remaining symbols are assigned the value null.
Multiple assignment effectively means that functions can return multiple values usefully.
i24 : f = i -> (i,i^2)
o24 = f
o24 : FunctionClosure
|
i25 : (r,s) := f 9
o25 = (9, 81)
o25 : Sequence
|
i26 : r
o26 = 9
|
i27 : s
o27 = 81
|
installing methods for binary operators
-
- Usage:
X OP Y := (x,y) -> ...
-
Inputs:
-
Outputs:
-
the value of the expression is the same as the function on the right hand side
-
Consequences:
-
the function on the right hand side is installed as the method for X OP Y. See the next subsection below for using it.
The first line of the following example illustrates the syntax above.
i28 :
String * String := peek;
|
i29 : "left" * "right"
o29 = ("left", "right")
|
i30 : String * Number := peek;
|
Warning: the installation of new methods may supplant old ones, changing the behavior of Macaulay2.
using methods for binary operators
-
- Usage:
x OP y
-
Inputs:
-
x, an object of type X
-
OP, one of the binary operators for which users may install methods, listed above. The operator SPACE, indicating adjacency, may be omitted from the usage above.
-
y, an object of type Y
-
Outputs:
-
the previously installed method for X OP Y is called with arguments (x,y), and its return value is returned. If no such method has been installed, then Macaulay2 searches for a method for X' OP Y', where X' is an ancestor of X and Y' is an ancestor of Y (see inheritance for details).
The second line of the following example illustrates the syntax above.
i31 : "left" * 33
o31 = ("left", 33)
|
i32 : "left" * 3.3
o32 = ("left", 3.3)
|
i33 : ZZ + ZZ := (x,y) -> x+y+100
o33 = FunctionClosure[stdio:37:11-37:27]
o33 : FunctionClosure
|
Some methods for operators are
internal, and cannot be successfully overridden by the user, as we illustrate in the next example, where we try (and fail) to override the definition of the sum of two integers.
i34 : 3 + 4
o34 = 7
|
i35 : QQ // QQ := (w,z) -> (numerator w + numerator z)/(denominator w + denominator z)
o35 = FunctionClosure[stdio:39:12-39:80]
o35 : FunctionClosure
|
By contrast, division with remainder of rational numbers is not internal, and can be overridden.
i36 : (3/5) // (6/7)
3
o36 = -
4
o36 : QQ
|
i37 : - String := peek;
|
installing methods for unary prefix operators
-
- Usage:
OP X = (x) -> ...
-
Inputs:
-
Outputs:
-
the value of the expression is the same as the function on the right hand side
-
Consequences:
-
the function on the right hand side is installed as the method for OP X. See the next subsection below for using it.
The first line of the following example illustrates the syntax above.
i38 : - "foo"
o38 = "foo"
|
i39 : - String := peek;
|
Warning: the installation of new methods may supplant old ones, changing the behavior of Macaulay2.
using methods for unary prefix operators
-
- Usage:
OP x
-
Inputs:
-
OP, one of the unary prefix operators for which users may install methods, listed above.
-
x, an object of type X
-
Outputs:
-
the previously installed method for OP X is called with argument x, and its return value is returned. If no such method has been installed, then Macaulay2 searches for a method for OP X', where X' is an ancestor of X (see inheritance for details).
The second line of the following example illustrates the syntax above.
i40 : - "foo"
o40 = "foo"
|
i41 : String ~ := peek;
|
installing methods for unary postfix operators
-
- Usage:
X OP = (x) -> ...
-
Inputs:
-
Outputs:
-
the value of the expression is the same as the function on the right hand side
-
Consequences:
-
the function on the right hand side is installed as the method for OP X. See the next subsection below for using it.
The first line of the following example illustrates the syntax above.
i42 : "foo" ~
o42 = "foo"
|
i43 : String ~ := peek;
|
Warning: the installation of new methods may supplant old ones, changing the behavior of Macaulay2.
using methods for unary postfix operators
-
- Usage:
x OP
-
Inputs:
-
x, an object of type X
-
OP, one of the unary postfix operators for which users may install methods, listed above.
-
Outputs:
-
the previously installed method for X OP is called with argument= x, and its return value is returned. If no such method has been installed, then Macaulay2 searches for a method for to X' OP, where X' is an ancestor of X (see inheritance for details).
The second line of the following example illustrates the syntax above.
i44 : "foo" ~
o44 = "foo"
|
i45 : source String := peek;
|
installing unary methods for method functions
-
- Usage:
f X := (x) -> ...
f(X) := (x) -> ...
-
Inputs:
-
f, a previously defined method function. A method function may be created with the function method.
-
X, a type
-
(x) -> ..., a function
-
Consequences:
-
the function on the right hand side is installed as the method for assignment to f X. See the next subsection below for using it.
The first line of the following example illustrates the syntax above, using
source, which happens to be a method function.
i46 : source "foo"
o46 = "foo"
|
i47 : source String := peek;
|
Warning: the installation of new methods may supplant old ones, changing the behavior of Macaulay2.
using unary methods for method functions
-
- Usage:
f x
-
Inputs:
-
f, a method function
-
x, an object of type X
-
Outputs:
-
the previously installed method for f X is called with argument x, and its return value is returned
The second line of the following example illustrates the syntax above, using
source, which happens to be a method function.
i48 : source "foo"
o48 = "foo"
|
i49 : source(String,Number) := peek;
|
installing binary methods for method functions
-
- Usage:
f(X,Y) := (x,y) -> ...
-
Inputs:
-
f, a previously defined method function. A method function may be created with the function method.
-
X, a type
-
Y, a type
-
(x,y) -> ..., a function
-
Consequences:
-
the function on the right hand side is installed as the method for f(X,Y). See the next subsection below for using it.
The first line of the following example illustrates the syntax above, using
source, which happens to be a method function.
i50 : source("foo",33)
o50 = ("foo", 33)
|
i51 : source("foo",3.3)
o51 = ("foo", 3.3)
|
i52 : source(String,String) := peek;
|
Warning: the installation of new methods may supplant old ones, changing the behavior of Macaulay2.
The same syntax works for 3 or 4 arguments.
using binary methods for method functions
-
- Usage:
f(x,y)
-
Inputs:
-
f, a method function
-
x, an object of type X
-
y, an object of type Y
-
Outputs:
-
the previously installed method for f(X,Y) is called with arguments (x,y), and the return value is returned. If no such method has been installed, then Macaulay2 searches for a method for f(X',Y'), where X' is an ancestor of X and Y' is an ancestor of Y (see inheritance for details).
The second line of the following example illustrates the syntax above, using
source, which happens to be a method function.
i53 : source("foo","bar")
o53 = ("foo", "bar")
|
i54 :
|
The same syntax works for 3 or 4 arguments.
Another use of the operator := is for installing methods for creation of new objects. For details, see new.