By @morphic with very minor edits of mine:
ErgoScript (as well as ErgoTree) is typed, so accessing a register is an operation which involves some expected type given in brackets. Thus SELF.R4[Int] expression should evaluate to a valid value of the Option[Int] type.
For example val x = SELF.R4[Int] expects the register, if it is present, to have type Int.
There are three cases:
-
If the register doesn’t exist. Then
val x = SELF.R4[Int]succeeds and returns the None value, which conforms to any value of typeOption[T]for any T. (In the example above T is equal toInt). Callingx.getfails when x is equal to None, butx.isDefinedsucceeds and returnsfalse. -
If the register contains a value
vof typeInt. Thenval x = SELF.R4[Int]succeeds and returnsSome(v), which is a valid value of typeOption[Int]. In this case, callingx.getsucceeds and returns the valuevof typeInt. Callingx.isDefinedreturnstrue. -
If the register contains a value
vof type T other thenInt. Thenval x = SELF.R4[Int]fails, because there is no way to return a valid value of typeOption[Int]. The value of register is present, so returning it as None would break the typed semantics of registers collection.
In some use cases one register may have values of different types. To access such register an additional register can be used as a tag.
val tagOpt = SELF.R5[Int]
val res = if (tagOpt.isDefined) {
val tag = tagOpt.get
if (tag == 1) {
val x = SELF.R4[Int].get
// compute res using value x is of type Int
} else if (tag == 2) {
val x = SELF.R4[GroupElement].get
// compute res using value x is of type GroupElement
} else if (tag == 3) {
val x = SELF.R4[ Array[Byte] ].get
// compute res using value x of type Array[Byte]
} else {
// compute `res` when `tag` is not 1, 2 or 3
}
} else {
// compute value of res when register is not present
}