Variants¶
Variants hold exactly one of a set of fixed types.
datatype Constant(int value);
datatype Add(Value& left, Value& right);
datatype Multiply(Value& left, Value& right);
variant Value = Constant | Add | Multiply;
At any time an object of type Value will contain exactly one of Constant, Add or Multiply.
Datatype Short Syntax¶
A syntactic special case of variant is datatype <name> = ...:
datatype Value =
Constant(int value) |
Add(Value& left, Value& right) |
Multiply(Value& left, Value& right);
This is identical to the code shown above; this more concise form is desirable unless the variant should contain non-datatype values (e.g. a class):
class Constant { }
class Add { }
class Multiply { }
variant Value = Constant | Add | Multiply;
Extracting elements¶
Elements of a variant can be extracted using if or switch.
Switch¶
int compute(Value value) {
switch (value) {
case Constant(int constant) {
return constant;
}
case Add(Value& left, Value& right) {
return compute(left) + compute(right);
}
case Multiply(Value& left, Value& right) {
return compute(left) * compute(right);
}
}
}
If¶
Note
Not yet implemented.
int getConstantOrZero(Value value) {
if (Constant constant = value) {
return constant.value;
} else {
return 0;
}
}
Method Calls¶
Note
Not yet implemented.
If there are common methods across all of the variant sub-types then these can be called via the variant:
int Constant::depth() const {
return 0;
}
int Add::depth() const {
return max(@left.depth(), @right.depth());
}
int Multiply::depth() const {
return max(@left.depth(), @right.depth());
}
int depth(const Value& value) {
return value.depth();
}
Templates¶
A variant can contain a templated type:
template <typename T>
variant optional = T | None;
import optional<Value> parse();