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

The void

We saw in the last section that the equate-at operator a) unhooks a member from its variable, then b) wires it up to a different variable. As we shall see now, there is a way to skip (b) and just leave a member pointing out into the ether.


    temp1 =@ nothing
   

An alternative syntax is:


    temp1 =@ *
   

The asterisk `*' and `nothing' are synonyms for the void operator. After running either of the lines above, we will not be able to do anything with temp1 until we re-alias it to someplace else. If we are unsure whether an object points into the void, we can test it using the reference-comparison operator:


    if temp1 == @nothing
       print("out of order..\n")
    endif
   

One obvious benefit of having a void is that it's good for storing members that we temporarily don't need. The void is a place of naught, no data and no code, and members stashed there don't use memory, jam arrays or otherwise bother our program. Yazoo won't allow us to accidentally use a void member for any data transactions: for example, temp2 = temp1 now gives us a void-member error. If we decide we need temp1 again, we can always reassign it new storage space (e.g. temp1 :: string if it was a string) or hook it on to an existing variable (temp1 =@ str_7) and it will work again as new.

There are actually two uses of the word `void' in this document that are important to keep logically separate. A void member in the sense we were just using is one that has no storage space. Alternatively, a void-typed member is one with essentially no type restriction on what it can point to. An absence of type is considered by Yazoo to be the most general type, and this gives void-typed members some special uses. By making a definition like a :: * we are doing two things: we are defining a member `a' with no type, and we are neglecting to give it storage space. Yazoo accomplishes both of these by use of the void operator.

Members that are defined with a void type can later be specialized to any other type by a second use of the define operator `::'. Circumstances actually arise where one may want to define a member whilst keeping options open as to the type of variable it will target: for example in the case of optional function arguments that the user defines. In that situation we postpone the type definition by initially defining the member void, and then later specialize by redefining it as another type.


    any_var :: *
    ...
    any_var := 2.5   | turn any_var into a double
   

Specializing a type---restricting to a subtype of its original type---is always allowed in Yazoo. In fact, that is the only type change that is ever allowed. One can never take a slong member and turn it back into nothing; it must be removed and reallocated.

Members that have no type are actually most useful in and of themselves. They can alias any variable.


    any_var :: *
    x :: slong
    y := "Hello"
    z := { z1 :: double, z2 :: single }
   
    any_var = @x
    any_var = @y
    any_var = @z
   

Normally, when the define operator creates a new member, it both assigns it a type and gives it a new variable. But, as a child of the void, member any_var has a nil type and hence can target any variable in the program.

The culmination of the previous section was in making a distinction between members and variables. We can see that this distinction muddies the notion of `type' that we have been bandying around. After any_var is aliased to x, does any_var have a null type or is it a signed long? Well, that depends on whether you are asking about the member's type, or the type of the variable it points to. Both members and variables have types, and in general (as in the example above) they may be different.

Our example foreshadows a point that we will flesh out later on: a member's type specification determines which variables it is allowed to point to. The rule is that a member can only target variables with the same type, or having a sub-type derived from its own. (Sole exception: all members can target `*', but the void hardly qualifies as a variable.) Since any type specification can be thought of as nothing plus whatever it is (x = 0 + x), all types are, in a sense, subtypes of the void. A member with a void type is therefore compatible with any target variable.

Now that we have seen how a member's type may differ from its target's, we are at last in a position to introduce two further, comparatively obscure members of the define-equate operator family.

The variable-define operator `@::' is identical to ordinary define (::), except that it only acts on the variable while leaving the member's type unchanged. In the example below, it is used twice to allocate storage for an untyped member.


    any_var :: *
    any_var @:: slong
    ...
    any_var =@ *
    any_var @:: string
   

Two points are worth making here. 1) We could almost have gotten away with using the ordinary define operator on the second line (any_var :: slong). But doing so would have specialized any_var to a slong, resulting in a type mismatch on the last line. 2) Unlinking any_var (2nd-to-last line) was necessary because define operators will never make a new variable unless they are forced to, either because they have just created the member or because the existing member was pointing into the void. Had we left out the void-aliasing step, Yazoo would have tried to redefine the existing slong variable as a string, causing a type-mismatch error.

By the way, the first line in the last example above was actually unnecessary. The variable-define operator will create a new member if none exists, but that member's type will be void regardless of the type of the variable that was created. Note that unlike `=@', we cannot insert a space anywhere in the operator: `@ ::' will cause a syntax error.

The member-define operator `*::' is the counterpart to variable-define: it operates only upon the member, without affecting any variable that member may target. It gets its symbol from the fact that, if one uses member-define to define a new member, it will indeed create a member of the desired type but it will not bother to create a variable for it, so the member will initially have no target.


    ul1 *:: ulong
    print(ul1)     | will cause an error
   

The above code causes a void-member error since ul1 has no associated variable. (The `void' in void-member always refers to the lack of a member's target variable -- its type is still ulong, not void.)

On the other hand, if we were to use member-define on a pre-existing member, then that member would just stay linked to whatever target variable it was pointing at (the void if none). As with the standard define operator, member-define can specialize a void member's type; but a specialized type such as ulong can never be generalized back to the null void type.


Prev: Aliases   Next: This and that


Last update: July 28, 2013

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