Getting Started Documentation Glish Learn More Programming Contact Us
Version 1.9 Build 1556
News FAQ
Search Home


next up previous contents index
Next: Constant Values Up: Values, Types, and Constants Previous: Arrays

Subsections



References

A reference is an alias to another variable, record field, or, for some types, a portion of a variable or record field. It provides a mechanism to allow two or more variables to refer to the same value. References are created using the ref operator.


Whole Value References

The most straight forward type of references are ``whole value'' references. In this case, a reference is made into another variable or record field.


Creating References

Whole variable references are created as follows:
    a := 1:5
    b := ref a
    b[2] := 9
    print a
prints [1 9 3 4 5] and not [1 2 3 4 5]. If you now execute:
    a[3] := 121
b will equal [1 9 121 4 5] (as will a). References to record field are created in the the same way:
    rxd := [a = 3:1, b = "hello there"]

    sxd := [x = ref rxd.a, y = ref rxd.b]

    sxd.x[2] := -4            # changes rxd.a[2], too

    print rxd.a[2]
prints -4.


Breaking References

A very important point to keep in mind when using reference is the way references can be broken through assignment. This can be a source of unexpected problems. A reference allows two variables to refer to the same value, but assigning to either of the variables, as opposed to their elements, breaks the link. In the following,

    x := 1:3
    y := ref x
    x[3] := 9        # changes y[3], too
    y[1] := 10       # changes x[1], too
    x := 3:1         # !! breaks the reference !!
    x[2] := 121      # does NOT modify y
the next to last assignment of 3:1 to x, instead of subscripted elements of x, breaks the reference, and as a result, the final assignment does not modify y. After the last assignment, x equals [3, 121, 1], and y equals [10, 2, 9]. References to record fields behave in the same way.


Explicitly Maintaining References

The reference connection is maintained across assignment by explicitly using the val operator. For example, after executing:

    c := [1, 3, 7, 12]
    d := ref c
    val c := "hello there"
the value of d (and of course c) is the two-element string "hello there". Assigning to val d will similarly change the value of c.

The behavior of record fields are identical to other variables. For example,

    r := [foo = 1:3, bar = "hello there"]

    s := [a = ref r.foo, b = ref r.bar]

    s.a[2] := -4            # changes r.foo[2], too
    s.a := [T, T, T, T, T]  # doesn't change r.foo

    val r.bar := 1:7 ^ 2    # changes s.b, too

    print r.foo[2], s.b[5]
prints -4 followed by 25.

The second assignment makes s a record with two fields, a and b, which are references to r.foo and r.bar.

The third assignment changes s.a[2] and r.foo[2] to be -4.

The fourth assignment breaks the link between s.a and r.foo, because s.a is assigned to the entire variable and not just some of its elements.

The fifth assignment modifies both r.bar and s.b to be a vector of the first 7 integers squared. Without the val operator, only r.bar changes, and the link between r.bar and s.b is broken.

It is also possible, though not recommended, to make the value referred to by a reference constant. This is done as follows:

    c := 1
    d := ref c
    const val d := 2
The last assignment changes c to a constant value, and d is a reference to c. After this, c cannot be modified.


Partial Value References

Partial value references can be created for any of the vector types. These references are created much like whole value references, but partial value references reference only a portion of the value. They also have more restrictions on their use than whole value references.

Creating References

Partial value references are also created with the ref operator. Unlike whole value references, partial value references create an alias to a ``sub-vector'' or ``sub-array''. That is, they reference a portion of another vector or array. So for example,

    vec := [1:10]
    svec := ref vec[5:9]
    svec[4] := 20           # modifies vec[8], too
Here a vector with ten elements, vec, is created, and then a reference to a portion of that vector is created, svec. Modification to any of svec elements changes the respective elements in vec. In this case, modifying the forth element in svec also changes the eighth element of vec. The length of svec is 5 not 10.

Partial value references are created for vector or array valued fields in the same way. For example,

    xle := [x=1:10, l=10:1, e=[2,7]]
    m := [t=ref xle.x[9:10], u=ref xle.l[9:10], v=ref xle.e]

    m.u[2] := m.t[2]            # modifies xle.l[10] as well
This example shows how sub-vector references of fields are similar to whole value references of fields. It is important to note, however, that you cannot take a partial value reference of a record. So,
    mz := ref xle["x e"]
is not valid.

Partial value references can also be created for arrays, and this is probably where they prove most useful. In the following,

    base := array(0,5,5)
    diag := ref base[array(1:5,5,2)] # a vector
    lower := ref base[4:5,]          # a 2x5 array
    diag[3] := 1                     # modifies base[3,3], too
    lower[1:2,[1,5]] := 5            # modifies base[4:5,[1,5]],
                                     # AND diag[5], as well
In this example, an array, base, is created. Then two partial value references, diag and lower, are created. The partial reference diag references elements along the diagonal of base, and the partial reference lower references the fourth and fifth rows of base. Modifying elements of either of the references modifies the corresponding elements of base.

Breaking References

It is important to realize that partial value references are broken the same way as whole value references. Continuing with the previous example,

    diag := 5:9                      # !! breaks reference !!
    lower[2,2] := 22                 # modifies base[5,2], also
the assignment to diag does not modify base. It breaks the reference link, and sets diag equal to 5:9. Assignments to lower elements, e.g. the second one, still modify base because that link remains intact.

Breaking partial value references to record fields happens identically.


Explicitly Maintaining References

There are more restrictions maintaining partial element references than there are with whole value references. The val operator is used to explicitly maintain partial value references. For example,

    a := 1:10
    b := ref a[6:10]
    val a := 10:1      # modifies b as well
Here a vector, a , and a partial value reference, b are set up. Modifying the entirety of a changes the elements which b references. This type of manipulation must be done very cautiously, however, because if the referenced vector, a, is shortened the reference vector may become invalid. In the following,
    val a := 6:10      # b is now INVALID!
a is assigned a shorter vector. At this point, b is now invalid, and subsequent indexing into b will generate error messages.

The partial value reference can also be assigned to, but with restrictions. The length of the new value must match the length of the reference. So,

    a := 1:10
    b := ref a[6:10]
    val b := 11:15     # modifies a as well
here b is used in a val assignment, but because the length of b and the length of the value being assigned are equal, all of b and the selected portion of a changes. If the lengths were not equal, an error message would be reported. Continuing this example,
    val b := 1:15     # ERROR!
An assignment such as this generates an error message.


next up previous contents index
Next: Constant Values Up: Values, Types, and Constants Previous: Arrays   Contents   Index
Please send questions or comments about AIPS++ to aips2-request@nrao.edu.
Copyright © 1995-2000 Associated Universities Inc., Washington, D.C.

Return to AIPS++ Home Page
2006-10-15