Initializing an object with Optional (nullable) fields

Say I have a type:

public type Element = {
    name: Text;
    attributes: [(Text, Text)];
    text: Text;
    children: [Element];
};

I can create instances of this type by specifying values for all of the fields:

var el: Element = {
  name = "my_name";
  attributes = [("my_key0", "my_val0"), ("my_key1", "my_val1")];
  text = "Some text";
  children = [];
};

But what I really want Element to represent is an object that always has a name, and may have one or more of the rest of the fields, i.e. it may have a couple attributes and some text, but no children as in the above example or it may have no attributes and no text but a few children or some text but no attributes or children. I looked into accomplishing this structure using variants, but I really need an Element to represent any possible permutation, not just a select named few.

I’d like to create instance of Element like the example above but I don’t want to have to specify empty values for the fields I’m not interested in. I figured if I made the fields Optional, they would default to null if not specified, but this doesn’t seem to be how things work.

public type Element = {
    name: Text;
    attributes: ?[(Text, Text)];
    text: ?Text;
    children: ?[Element];
};
var el: Element = {
    name = "my_title";
    attributes = ?[("my_key0", "my_val0"), ("my_key1", "my_val1")];
    text = ?"Some text";
};

results in

type error, expression of type
  {attributes : ?[(Text, Text)]; name : Text; text : ?Text}
cannot produce expected type
  {attributes : ?[(Text, Text)]; children : ?[Element]; name : Text; text : ?Text}

How can I create instances of Element by only specifying the fields I’m interested in, and have the non-specified fields default to null?

2 Likes

Unfortunately, that’s currently not supported.

Maybe before such a a feature is available, we’ll have “record updates”, where you can create a record from a record, changing just a few fields. Then you could create a defaultElement with all fields null, and create further elements by updating (in the purely functional sense) that value. That might at least alleviate some of the pain.

4 Likes

Following its pitfall avoidance philosophy, it is intentional that Motoko requires to be explicit about all initialisation, whether variables or fields. Default initialisation is a common source for bugs, since forgetting proper initialisation can happen by accident. And like all implicit behaviour, it obscures code for readers, who may not easily see what’s going, or can’t tell whether it was intended.

As @nomeata says, some form of record update or mixin is more likely to happen.

2 Likes