Identifier
Type
Identifiers define opaque, typed identifiers.
Rationale
When dealing with collections, it is often useful to be able to identify an element inside that collection by something other than its position.
Identifiers allow you to create strongly typed identifiers to support this use case.
A typical example is a collection of structs, where individual elements have no natural identity. You can create an identifier to store these structs inside a map.
struct Payment {
amount: Number,
paymentDate: LocalDate,
processed: Boolean
}
identifier PaymentId;
protocol[issuer, payee] Iou() {
var payments: Map<PaymentId, Payment> = mapOf<PaymentId, Payment>();
permission[issuer] pay(amount: Number) returns PaymentId {
var p = Payment(amount, now().toLocalDate(), processed = false);
var id = PaymentId();
payments = payments.with(id, p);
return id;
}
permission[payee] markProcessed(id: PaymentId) {
var processedPayment = payments.getOrNone(id).getOrFail().copy(processed = true);
payments = payments.with(id, processedPayment);
}
}
Declaration
An identifier type is declared by the identifier
keyword, followed by the type name, followed by a semicolon,;
.
Declaration of an identifier type is a top-level construct.
identifier MyId;
Instantiation
An identifier instantiation starts with the identifier's type name, followed by parentheses, similar to a function call. It takes no arguments.
When an identifier value is instantiated within NPL, it is assigned a random, unique value.
For example, given an identifier defined as:
identifier MyId;
creating a new typed identifier value looks like so:
var myId: MyId = MyId();
var yourId = MyId(); // type annotation is not required
Usages
An identifier parameter, field or variable is declared like any other variables with the user-defined identifier type
name. Values of an identifier type can be used as a key or value in a Map
. You can also return values of a
user-defined identifier type.
An identifier type can be imported from other packages using the use
import statement.
An identifier type can be annotated with @experimental
and @deprecated
annotations.
Operators
Comparison
Values of a user-defined identifier type can be compared for equality, ==
and inequality, !=
.
var myId: MyId = MyId();
var yourId: YourId = YourId();
function validComparison(myId: MyId, anotherMyId: MyId) returns Boolean -> {
return myId == anotherMyId;
};
Note that you cannot compare values of different identifier types.
// compile ERROR, myId and yourId have different types
function invalidComparison(myId: MyId, yourId: YourId) returns Boolean -> {
return myId == yourId;
}
Methods
While .toText()
standard library method is not supported for the values of a user-defined identifier type,
logging identifier values is still possible.