Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

choice

choice

§
(CHOICE_ELEMENT_TYPE 
type
)
:
Any

choice -- feature used for choice types

choice types provide algebraic sum types of all the generic arguments
provided to choice. A instance of a choice type is a tagged union of
the types provided as actual generic type parameters. This concept is
also called variant, sum type or coproduct in other contexts.

Syntactic sugar of the Fuzion language permits an alternative notation
for choice types with actual generics as follows

A | B | C | ...

which is equivalent to

choice A B C ...

The parser will directly convert the first notation into a choice type
with actual generics.

A field of choice type can be assigned a value of the same choice type
or of any of the actual generic type arguments provided to the choice
feature.

Two choice types choice A B and choice B A that differ only in the order
of their actual generic arguments are treated as different types.

Named choice types can be constructed through inheritance, i.e.,

C : choice A B is {}

creates a choice type of A and B with the name C. Two named choice types
D and E that inherit from choice with the same actual generic arguments in
the same order are nevertheless different types and their values are not
assignable to one another.

Named choice types may declare or inherit additional inner features as long
as these features are not fields. Also, declared inner features must not
build a closure that accesses outer features. Additional parents must be
unit types, i.e., they must not declare fields nor access features of any
of their outer features.

Note that all types provided must be distinct, it is not possible to
repeat the same type as in choice i32 i32 or float | float. If a sum
type of two or more equal types is desired, these types must first be
wrapped into a new type as illustrated in the following example:

Say we want to store a temperature that is given as a 32 bit integer
in degrees centigrade or degrees Fahrenheit. So we define two wrapper
features

centigrade(degrees i32) is {}
fahrenheit(degrees i32) is {}

Now we define the choice type using the wrapped i32 types, which are
distinct:

has_fever(temp centigrade | fahrenheit) bool is ...

When passing arguments to this feature, we need to wrap them accordingly:

has_fever (centigrade 37)
has_fever (fahrenheit 99)

When matching the choice type, we use the wrapper types and access the
argument field 'degrees' to access the i32 stored inside

match temp

NYI: Once Fuzion's match expression supports destructuring as well, we should
be able to extract the degrees directly as in

match temp

A choice type with no actual generic arguments is isomorphic to 'void', i.e, it
is a type that has an empty set of possible values.

Type Parameters

§
CHOICE_ELEMENT_TYPE
:
Any

Functions

§
 => 
String  
[Inherited from  Any]
create a String from this instance. Unless redefined, `a.as_string` will
create `"instance[T]"` where `T` is the dynamic type of `a`
§
 => 
Type  
[Inherited from  Any]
Get the dynamic type of this instance. For value instances `x`, this is
equal to `type_of x`, but for `x` with a `ref` type `x.dynamic_type` gives
the actual runtime type, while `type_of x` results in the static
compile-time type.

There is no dynamic type of a type instance since this would result in an
endless hierarchy of types. So for Type values, dynamic_type is redefined
to just return Type.type.
§
 => 
String  
[Inherited from  Any]
convenience prefix operator to create a string from a value.

This permits usage of `$` as a prefix operator in a similar way both
inside and outside of constant strings: $x and "$x" will produce the
same string.

Type Functions

§
 => 
String  
[Inherited from  Type]
string representation of this type to be used for debugging.

result has the form "Type of '<name>'", but this might change in the future

redefines:

§
 => 
Type  
[Inherited from  Type]
There is no dynamic type of a type instance since this would result in an
endless hierarchy of types, so dynamic_type is redefined to just return
Type.type here.

redefines:

§
(T 
type
)
 => 
bool  
[Inherited from  Type]
Is this type assignable to a type parameter with constraint `T`?

The result of this is a compile-time constant that can be used to specialize
code for a particular type.

is_of_integer_type(n T : numeric) => T : integer
say (is_of_integer_type 1234) # true
say (is_of_integer_type 3.14) # false

it is most useful in conjunction preconditions or `if` statements as in

pair(a,b T) is

=>

or

val(n T) is

§
 => 
String  
[Inherited from  Type]
name of this type, including type parameters, e.g. 'option (list i32)'.
§
 => 
String  
[Inherited from  Type]
convenience prefix operator to create a string from a value.

This permits usage of `$` as a prefix operator in a similar way both
inside and outside of constant strings: $x and "$x" will produce the
same string.

NYI: Redefinition allows the type feature to be distinguished from its normal counterpart, see #3913

redefines:

§
(a choice.this.type)
 => 
choice.this.type
explicitly tag value a to become choice
§
 => 
Type  
[Inherited from  Any]
Get a type as a value.

This is a feature with the effect equivalent to Fuzion's `expr.type` call tail.
It is recommended to use `expr.type` and not `expr.type_value`.

`type_value` is here to show how this can be implemented and to illustrate the
difference to `dynamic_type`.