Yazoo ---> Online Help Docs ---> Yazoo scripting ---> Working with variables

Other equate operators

As we saw in the last section, the define operator `::' is very similar to the equate operator `=', except that it copies `type', not data. It copies only type. So, following an example from the last section, if we execute


    Tom :: { ... }
   
    Tom.number = 63
   
    Bob :: Tom
   

then Bob's street number will be 0 even though Tom's street number is set to 63. Bob was defined as a variable of of Tom's type, and like Tom it began life with all numeric fields initialized to zero.

There is a way to define Bob so that it inherits Tom's data as well as its type, which is to use the define-equate operator `:='. So if we had instead defined Bob by writing


    Bob := Tom
   

then both Bob and Tom would have their number field initialized to 63. This is equivalent to


    Bob :: Tom
    Bob = Tom
   

The define-equate operator has problems when the type definition does not match the actual fields in the variable. The issue is that equate copies data from the fields that are actually present in a variable, whereas define creates fields based on the original type definition. Had we modified our template variable Tom so that its field structure no longer matched its original and immutable type definition, we would land ourselves a type-mismatch error.


    Tom :: { ... }
    Tom.country := "USA"
    Bob := Tom         | will cause an error
   

Here we've defined Bob according to Tom's intrinsic type, which is the structure in braces; then the equate half of the `:=' operator fails because Tom's actual contents differ from that intrinsic type by the extra country field.

The define-equate operator often also fails when the template variable was defined implicitly. Again, it is for the same reason: in an implicit definition the intrinsic type is set to a blank {}, but the contents of the variable were promptly increased to one member (see last section's discussion). As we see later, arrays are generally defined implicitly, so they usually cannot be used as a template for define-equate---this is probably the major practical limitation of this operator.

There are actually over a hundred members of the define-equate operator superfamily, of which bread-and-butter define (`::') and equate (`=') are the two most prominent. Only a handful of the others, such as `:=', have symbols that make them accessible via ordinary scripting. The next two sections will dwell in part on most of the remaining symboled operators. A further few operators which are used discreetly by the compiler will be described in a later chapter.

One operator superficially resembles equate, although it is technically an unrelated branch on the family tree. It is called `forced-equate' and is given the symbol `=!'. Like simple equate, forced-equate copies data between two variables, but they copy data in different ways and have different restrictions on their two arguments. A simple equate copies data from field to field, so the data structures contained within its two arguments must have the same number of primitive elements in the same hierarchy, and each corresponding primitive field must be of the same or a compatible type (i.e. integer to floating-point). By contrast, a forced equate simply takes the data contained in its right-hand argument and stuffs those N bytes in the same order into the left-hand variable. In a forced equate the byte sizes of the two variables must be the same, but there are no restrictions on how the storage space is parceled out within the destination variable.

When forcing an equate from an inlined numeric constant, remember that Yazoo interprets constants as either as signed long integers or floating-point doubles, according to the convention described in the earlier section on expressions. So on the author's old machine where long integers are 4 bytes and doubles are 8 bytes, a =! -4 and a =! 2e5 will copy 4 bytes while a =! 4. and a =! 2e10 will each copy 8 bytes.

An example where equate may be used but forced-equate fails is the following.


    pixel_coord :: { x :: y :: z :: ushort }
    real_coord :: { x :: y :: z :: double }
   
    ...
    pixel_coord = real_coord   | will pass
    pixel_coord =! real_coord  | will fail
   

The reason for this is that double-precision floating points generally take up 8 bytes whereas short integers usually take up only 2.

In the next two cases a forced equate can be used but not a simple equate.


    var1 :: {
       part1 :: {
           a :: double
           b :: ulong   }
       c :: sshort
    }
   
    var2 :: {
       a :: double
       b :: ulong
       c :: sshort
    }
   
    var1 =! var2    | OK so far
    var1 = var2     | no, this will not work
   

Here, although both var1 and var2 contain the same number of primitive variables, equate gets tripped up by their different groupings whereas the forced-equate is insensitive to this. Also:


    var1 :: {   a :: b :: c :: d :: sshort   }
    (var2 :: double) = 6.28319
   
    var1 =! var2    | works on the author's old machine
    var1 = var2     | won't work on any machine
   

Forced equate happily distributes the bit-representation of var2 among the four short integers of var1 (though the subsequent contents of var1 will be hard to interpret).

One nice thing about a forced equate is that it is especially likely to work (as in, not give a type-mismatch error) when a string is involved on the left-hand side. The reason is that, because a string's storage space is flexible, forced-equate will try to size the string to accommodate whatever data is not soaked up by any fixed-storage fields. (If there are multiple strings then the first one absorbs all the extra data.) So if we write, for example,


    chars :: {
       one :: ubyte
       two :: string
       three :: ubyte  }
   
    my_string := "Yazoo"
    chars =! my_string
   

then `Y' and the final `o' are encoded in the primitive members one and three respectively, while two will contain `azo'. Of course we still have to copy at least 2 bytes of data to fill the fixed-storage field: replacing the last line with chars =! "Y" will not work.


Prev: Composite variables   Next: Aliases


Last update: July 28, 2013

Get Yazoo scripting language at SourceForge.net. Fast, secure and Free Open Source software downloads