next up previous contents index
Next: Numeric Types Up: ValuesTypes, and Constants Previous: ValuesTypes, and Constants

Overview

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.

Glish Types

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 gif.

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.

Dynamic Typing

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 gif). For example,
    is_integer(ref 5)
returns true (see below, § 3.8, page gif).  

Type Conversions

 

  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 * .2
assigns 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_string
Details on how they do their conversions can be found in § 9.2, page gif.

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.   

Vectors

 

  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

Creating Vectors

 

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 gif). 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 gif.

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:7
yields
    [3, 4, 5, 6, 7]
and
    3:-2.7
yields
    [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.  

Length of a Vector

 

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.

Element-by-Element Vector Operations

 

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 gif 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] * 3
yields
    [3, 6, 18]
If neither operand  is a scalar but the two vectors have different sizes then a run-time error occurs.

Accessing Vector Elements

 

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.

Modifying Vector Elements

 

You can also    set a vector element using the [] operator:

    a[1] := 3
assigns 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 gif. 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] := 32
results 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] := 19
sets 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 gif, for a description.  


next up previous contents index
Next: Numeric Types Up: ValuesTypes, and Constants Previous: ValuesTypes, and Constants

Thu Nov 13 16:44:05 EST 1997