The second type of variable in Cicada is a composite variable, equivalent to a structure variable in C. Composite variables are collections of members defined inside of curly braces, just as in C. Member definitions can go on their own lines, but make sure the opening brace is on the first line.
StreetAddress :: {
number :: int
street :: string
}
If we don’t care about the member names we can leave them out.
StreetAddress :: { int, string }
StreetAddress is a proper variable with its own storage, but we can also treat it as a data type.
PetersPlace :: StreetAddress
In general any Cicada variable A can be used to define other variables B and C. In a sense, the define operator copies ‘type’, but not data.
We access members of a composite variable the same way in Cicada as we do in C, using a period. For example (using the original definition with member names):
PetersPlace.number = 357
PetersPlace.street = "Bumbleberry Drive"
Composite variables may be nested inside one another, either using previously-defined types or by nesting curly braces.
FullAddress :: {
first_line :: StreetAddress
second_line :: {
city :: state :: string
zip :: int
}
}
In this case, we need to use a ‘.’ twice to access any of the primitive fields.
FullAddress.first_line.number = 357
Notice that members of composite variables can also serve as data types.
GeneralWhereabouts :: FullAddress.second_line
GeneralWhereabouts.city = "Detroit"
The type specification of a composite variable determines how it looks initially, but its internal structure can be rearranged later on.
PaulineAddress :: FullAddress
remove PaulineAddress.first_line.street | it's a PO box
PaulineAddress.country :: string | in another country
By the end PaulineAddress will have a three members including one named country, and the street member of first_line will be missing. One potential pitfall is that these modifications did not change the type specification, so if we ever try to copy its type and data in one operation, then we’ll have problems.
> PaulinesDogAddress := PaulineAddress
Error: type mismatch
Assignment and equality-testing work with whole composite variables just like they do with primitive variables:
Tom :: Bob :: StreetAddress
...
Tom = Bob
if Tom == Bob then ( | yes, they will be equal
print("They're sharing a room.\n")
)
We were allowed to assign and compare Tom and Bob because they have the same { number, string } structure.
Numeric operations and comparisons do not work with composite variables, even if all their members are numeric. Expressions like Tom+Bob and Tom > Bob will always cause an error.
Last update: November 12, 2025