.. default-domain:: chpl
.. index:: single: unions
Unions have the semantics of records, however, only one field in the union can contain data at any particular point in the program's execution. Unions are safe so that an access to a field that does not contain data is a runtime error. When a union is initialized, it is in an unset state so that no field contains data.
Warning
Unions are currently unstable and may change in ways that will break their current uses.
.. index:: single: union single: declarations; union
A union is defined with the following syntax:
union-declaration-statement:
'extern'[OPT] 'union' identifier { union-statement-list }
union-statement-list:
union-statement
union-statement union-statement-list
union-statement:
procedure-declaration-statement
iterator-declaration-statement
variable-declaration-statement
empty-statementIf the extern keyword appears before the union keyword, then an
external union type is declared. An external union is used within Chapel
for type and field resolution, but no corresponding backend definition
is generated. It is presumed that the definition of an external union
type is supplied by a library or the execution environment.
.. index:: single: types; unions single: union types
The syntax of a union type is summarized as follows:
union-type:
identifierThe union type is specified by the name of the union type. This simplification from class and record types is possible because generic unions are not supported.
.. index:: single: unions; fields
Union fields are accessed in the same way that record fields are accessed. It is a runtime error to access a field that is not currently set.
Example (fieldAccess.chpl).
union U { var x: int; var y: real; } var u: U; u.x = 3; // sets field x writeln(u.x); writeln(u.y); // runtime error: field y is not set
The currently active field of a union can be queried at runtime with the :proc:`~ChapelUnion.union.getActiveIndex` method. If the union is not yet initialized, then :proc:`~ChapelUnion.union.getActiveIndex` returns -1.
Example (getActiveIndex.chpl).
writeln(u.getActiveIndex()); // prints -1 u.y = 3.0; // sets field y writeln(u.getActiveIndex()); // prints 1
Each union field also has an associated index, this can be queried by accessing the field name as a member of the union type.
Example (fieldIndex.chpl).
union U { var x: int; var y: real; } writeln(U.x); // prints 0 writeln(U.y); // prints 1
Union fields should not be specified with initialization expressions.
.. index:: single: unions; assignment
Union assignment is by value. The active field of the union on the right-hand side of the assignment is assigned to same field of the union on the left-hand side, and this field is made active.
.. index:: single: unions; equality single: unions; inequality single: unions; == single: unions; != single: == (union) single: != (union)
Default comparison operators are defined for unions such that if no more specific comparison is found, these defaults will be used. These default comparisons are defined using the following signatures:
operator ==(a: union, b: union) : bool
operator !=(a: union, b: union) : boolWhen these comparisons are applied to two union values of distinct types, a compiler error is generated.
These default comparisons consider two union values to be equal if (a) both union have the same active field and (b) those fields are considered equal via ==. Otherwise they are considered not equal.
.. index:: single: unions; pattern matching
There are two primary ways to perform pattern matching on unions: using a
select statement or using the :proc:`~ChapelUnion.union.visit` method.
Pattern matching allows users to decompose a union based on the currently
active field.
Example (patternMatchSelect.chpl).
Unions can use a
selectstatement to perform pattern matching on the active field of the union.select u { when U.x { writeln("x is active with value ", u.x); } when U.y { writeln("y is active with value ", u.y); } otherwise { writeln("no field is active"); } }Example (patternMatchVisit.chpl).
The :proc:`~ChapelUnion.union.visit` method can be used to perform pattern matching on the active field of the union, with an associated visitor functor.
u.visit(proc(x: int) { writeln("x is active with value ", x); }, proc(y: real) { writeln("y is active with value ", y); });
It is also possible to check the active field of a union with normal conditionals.
Example (patternMatchConditional.chpl).
if u.getActiveIndex() == U.x { writeln("x is active with value ", u.x); } else if u.getActiveIndex() == U.y { writeln("y is active with value ", u.y); } else { writeln("no field is active"); }
.. index:: single: unions; methods