Cicada ---> Online Help Docs ---> Cicada scripting ---> Variables

The void

There is one last way to define a variable, and that is not to define it as anything at all. There are two ways of writing this:


    var1 :: nothing
    var2 :: *
   

nothing and * are synonyms for the void operator. If var1 is defined as void then we will get a void-member error if we try to access its data. In fact, one of the few things we can do with a void member is to test whether it is void or not, using the reference-comparison operator ==@.


    if var1 == @nothing then &
       print("out of order..\n")
   

One way to make use of a void member is to redefine it.


    var1 :: nothing
    var1 :: [1000] string
   

We could have redefined var1 as anything: a primitive or composite variable, function, etc. But once it’s been redefined once var1 cannot be redefined again except to the same type or a derived type (see inheritance).

What is the use of defining void-typed variables (aside from the fact that they don’t take up space until we redefine them)? The main reason is that 1) members defined this way have no type until they are redefined, and 2) members without a type can alias any other member, because in a sense all data types are derived from the void. This works as long as we don’t redefine the alias (i.e. we have to just use the =@ operator, not :=@).


    any_var :: *
    x :: int
    y := "some string"
    z :: { double, int }
   
    any_var = @x
    any_var = @y
    any_var = @nothing
    any_var = @z
   

The fact that the void is the universal parent type also explains why void members can be redefined. Cicada always permits an existing member’s type to be specialized---restricted to a subtype of its original type---but never changed to an unrelated type. And we cannot un-specialize: an int member cannot be turned it back into nothing, except by removing and reallocating the member.

There are actually two uses of the word ‘void’ in this document that are important to keep logically separate. A void member is one that has no storage space. But a void-typed member is one with essentially no type restriction on what it can point to. A definition like a :: * does two things: it defines a member ‘a’ having no type, and it therefore neglects to give ‘a’ any storage space.

Cicada also distinguishes between member types and variable types. For example, after any_var was aliased to x, did any_var have a null type or was it an int? Well, that depends on whether you are asking about the member’s type (which was void), or the type of the variable it points to (an integer). Both members and variables have types, and in general they may be different. A member’s type specification determines which variables it is allowed to point to. The rule is that a member can only target variables of the same type, or having a sub-type derived from its the member’s type. (One exception: any member can be aliased to the void to free up storage space.)


Prev: Aliases    Next: Other define and equate operators


Last update: May 8, 2024