We begin with an overview of the types of values supported by Glish, giving a brief description of each type and introducing the notions of dynamic typing, type conversion, and vector and array values. We discuss each type in detail in § 3.2-§ 3.10 below.
There are fourteen types of values in the Glish type system:
Every value in a Glish script has one of these types. The function type_name returns as a string the name of its argument. For example,
type_name(2.71828)returns ``double". type_name is more fully described in § 9.1, page .
For most types there are ways of specifying constants representing values of the type. In the example above, 2.71828 is a constant of type double. The discussion of types in § 3.2-§ 3.10 below includes a description of how to specify constants for the types.
Glish variables are dynamically typed , meaning that their type can change with each assignment. Before any assignment has been made to a variable its value is F, the ``false" constant, and its type is thus boolean. So in the following:
a := 5 a := 2.71828 a := "hello there"before the first statement is executed, a's type is boolean; after the first statement, its type is integer; after the second, double; and after the third, string.
To see if a value has a particular type X, call the function is_X, which will return true if the value has that type and false otherwise. For example, the function call
is_integer(5)will return a boolean value of true, while
is_double(5)returns a value of false. The one exception is that there is no is_reference() function for determining whether a value is a reference type; instead you must use the type_name() function (§ 9.1, page ). For example,
is_integer(ref 5)returns true (see below, § 3.8, page ).
Some types are automatically converted to other types as needed. For example, an integer value can always be used where a double value is expected. The following:
a := 5 b := a * .2assigns the double value 1.0 to b; a's type remains integer. Similarly, a double value can be converted to a dcomplex value. Automatic conversions are limited to converting between numeric types, and converting a reference type to the type it refers to.
Other types require explicit conversion. For example, the following expression is illegal:
5 * "1234foo"but the string can be explicitly converted to an integer using the function as_integer. The following yields an integer value of 6170:
5 * as_integer("1234foo")The following functions are available for explicit type conversion:
as_boolean as_byte as_short as_integer as_float as_double as_complex as_dcomplex as_stringDetails on how they do their conversions can be found in § 9.2, page .
Still other types cannot be converted at all. For example, a function type cannot be converted to any other type.
Type mismatches result in run-time errors.
Most Glish types correspond to a vector of values rather than a single value. For example,
a := [1, 2, 6]assigns to a a vector of three elements, each an integer. A vector with only one element is called a scalar. For example,
[5]is an integer scalar and is identical in all ways to the constant:
5
In general, you create vectors by enclosing a comma-separated list of values within square brackets ([]). The values must all be automatically convertible to one another (see § 3.1.3, page ). This means that they must either all be numeric or they must all be the same type. If they are numeric then they are converted to the ``highest" type among them, as discussed in § 3.2.2, page .
The individual values inside the []'s are not restricted to scalars; vectors can be included, too, and will be expanded ``in-line". For example,
[1, 7, [3, 2, [[[5]]]], 4]is equivalent to
[1, 7, 3, 2, 5, 4]
integer vectors can also be created using the built-in : operator, which returns a vector of the integers between its operands. For example,
3:7yields
[3, 4, 5, 6, 7]and
3:-2.7yields
[3, 2, 1, 0, -1, -2]
You don't have to list any values inside the brackets:
a := []assigns to a an empty vector of type boolean. Note that such empty vectors have the special property that they can be intermixed with vectors of types that would otherwise be incompatible. For example,
["foo", "bar", []]yields a two-element string vector, while
["foo", "bar", [T]]results in an error because the elements of the constructed vector do not have compatible types.
You can also create vectors using the seq function; see § 3.6 and § 9.3 for a description.
The length function returns the length of one or more vectors. It can be abbreviated as len. For example,
len( [3, 1, 4, 1, 5, 9] )returns the integer value 6, and
1:len(a)is a vector of the integers from 1 to the length of a.
If more than one vector is supplied as arguments to length, a vector is returned where each element of the resultant vector is the length of the corresponding parameter, so
len( 1:3, 1:9, 4:15 )returns the vector
[3, 9, 12]because the length of the first parameter was 3, the length of the second parameter was 9 and the length of the final parameter was 12.
The various arithmetic, logical, and comparison operators all work element-by-element when given two equal-sized vectors as operands. For example,
[1, 2, 6] * [5, 0, 3]yields the vector
[5, 0, 18]See § 3.2.3, page for more information on the behavior of arithmetic operators.
Single-element vectors are referred to as scalars. If one operand is a multi-element vector and the other a scalar then the scalar is paired with each vector element in turn. For example,
[1, 2, 6] * 3yields
[3, 6, 18]If neither operand is a scalar but the two vectors have different sizes then a run-time error occurs.
Vector elements are accessed using the [] operator. For example,
a[5]returns the 5th element of a. Here 5 is a vector index. The first element is retrieved using an index of 1 (a[1]; not a[0] as would be the case in C). Indices less than 1 or greater than the size of the vector result in run-time errors.
For example,
(5:10)[3]yields 7. The [] operator has higher precedence than the : operator, so
5:10[3]results in an error because the vector being indexed (the scalar [10]) has only one element and not three.
You can also set a vector element using the [] operator:
a[1] := 3assigns 3 to the first element of a. The new element value must either be of the same type as the vector, or both the vector and the new element must be of numeric type, in which case the vector's type becomes the ``highest" of the two types, as discussed in § 3.2.2, page . For example, if in the above assignment a's type was double then the value of 3 would be converted to 3.0; if a's type was boolean then a would first be converted to integer and then its first element set to the integer 3.
It is possible to extend a numeric vector by setting an element beyond its end. Any ``holes" between the previous end of the vector and its new end are filled with zeroes (``false" for boolean values). So for example,
a := 1:5 a[8] := 32results in a having the value [1, 2, 3, 4, 5, 0, 0, 32]. Furthermore, a previously undefined variable can be set to a vector value by setting an element to a numeric value:
b[4] := 19sets b to the value [0, 0, 0, 19].
You also can access or modify more than one vector element at a time; see § 3.6, page , for a description.