Some related discussions: making parameters optional certainly makes many of the Attrs more informative during compile-time.
Benefit of Optional<T>
and Non-Nullable Refs.
For example, in the case of the topi operator sum(x, axis)
, the true type of axis is Optional<Array<Integer>>
. Making this intention clear would help to make the code more readable. Because we need to explicitly call value()
function in Optional<T>
to get the underlying type T
, it would reminds the developer to do not null check before doing so.
Another example is that in most cases our IR nodes’s fields are expected to be not-null. Making some of the IR refs(Expr, Stmt) not non-nullable will increases the robustness in our codebase via statically type checking.
Engineering Cost for non-nullable ObjectRefs
Non-nullable refs does introduce a bit of engineering overhead. In particular, non-nullable refs may not have a default constructor(the default behavior of nullable refs defaults to nullptr) to let us enjoy more compile time checks. This means we need to introduce the member init constructor for each ObjectNode.
Say PrimExpr is notnullable.
class RangeNode : public Object {
public:
PrimExpr min;
PrimExpr extent;
// because min/extent does not have default constructor
// we have to explicitly create such constructors
RangeNode(PrimExpr min, PrimExpr extent)
: min(min), extent(extent) {}
// rest of the code
};
class Range : public ObjectRef {
public:
Range make_by_min_extent(PrimExpr min, PrimExpr extent) {
// old-style no longer works, because there is no default constructor.
// auto n = make_object<RangeNode>();
// n->min = std::move(min);
// n->extent = std::move(extent);
// return Range(n);
// Need to directly call the constructor of RangeNode to intialize the fields.
return Range(make_object<RangeNode>(min, extent));
}
};
Sugars Enabled by Optional
Because Optional<T>
overloads operator bool
, and comparison operators, it enables certain sugars to reduce the length of the code
// get a value for return null
Optional<String> GetValueOrNull();
void Example() {
if (auto opt = GetValueOrNull()) {
// opt contains not-null value
String value = opt.value();
// code
}
}
Optional<T>
can directly compares to T
, by checking the optional to be notnull then run the comparison.
void Example(PrimFunc f) {
if (f->GetAttr<Integer>(key, 0) == 10) {
}
}