Candid explainer: First post published


If you want to make null a variant that is fine with me and even a shortcut Null candid keyword as long as over the wire it is a variant. The Option-type can as well be a variant over the wire I think that is better

We already went over this, reserved can be used here (or empty).

You can use reserved here as well. (And side point why on earth would anyone want to use a canister that is made specific for a map key,value store as a set? What an example.)

  • This can only be backwards compatible if the canister checks for people sending options and skips them.
  • a canister which makes new clients send it a null value is just a waste.
  • if this was a legitimate case, the canister can use the type: Reserved .

Indeed, we already went over this, and I already explained earlier that empty can not be used, since you would not be able to construct any values of the variant then.

Technically, reserved could be used, but would not convey the same information, namely that the argument is unused and doesn’t need to be stored. Reserved rather means that the argument can be anything but you don’t care (yet) what it is.

Quite a practical example, in fact. When you only have a map at your disposal but need a set, that’s what you do. Been there done that.

I think you missed out on the higher-order nature of this example: it’s the canister itself who sends these values.

It has no choice if it wants to avoid breaking existing clients. And FWIW, sending values of type null takes up zero space in the wire format.

Again, that would not be a backwards-compatible choice.

@rossberg I see, you put this line in the spec:
// NB: M(_ : empty) will never be called
This line is a waste. Only there to make the null value try to make sense. If this line (the M-function of the Empty type) is: M(_ : empty) = . this is correct because it is, in the most literal and logical sense, an empty data-sequence (as it says in the spec: “The following notation is used: ‘.’ is the empty byte sequence.” the spec uses the word empty here because the ‘.’ is an empty byte-sequence which fits with the word empty. ). The Empty-type has a type-code in the current-spec: 0x6f, the only reason you are saying it can’t be used as the value of a variant is because of this line: // NB: M(_ : empty) will never be called , which can change for the line: M(_ : empty) = . which will make the Empty-type good for the use as a value in the variants (it already has a type-code). Then we can get rid of that null type.

Now you are confusing null and empty, which are very different beasts.

One take-away from this thread perhaps is that the name empty is confusing – apparently, some read that as “type with an empty value”, not “empty type”, and even explaining it several times doesn’t make up for the initial misunderstanding.

I wonder if we should rename it to impossible?

Maybe. How about none?

But TBH I think empty is a fine name, and I am pessimistic that there exists a name that will significantly reduce confusion. Some things just need to be explained, no matter what the name, and the concept of a type without any values is certainly not intuitive.

the explainer was useful, thank you!