Optional chaining
Safely read nested instance fields when a link in the chain might be `nil`.
Use ?. instead of . to access an instance field or method. If the value on the left is nil, the whole access short-circuits to nil: no runtime error.
Chains like user?.profile?.address?.city walk each link only while the current value is a non-nil instance. A nil in the middle stops the rest of the chain and yields nil.
Optional chaining is read-only: you cannot assign through ?.. A missing property on a real instance still errors; ?. only guards against nil receivers.
Nested fields
Read through nested instance fields when every link exists.
class Address {
init(city) { this.city = city; }
}
class Profile {
init(bio, address) {
this.bio = bio;
this.address = address;
}
}
class User {
init(name, profile) {
this.name = name;
this.profile = profile;
}
}
var user = User("Rain", Profile("developer", Address("Kathmandu")));
print user?.name;
print user?.profile?.bio;
print user?.profile?.address?.city;output
Rain developer Kathmandu
nil root or middle
`nil` at any point in the chain returns `nil` for the rest.
class User {
init(name, profile) {
this.name = name;
this.profile = profile;
}
}
var nobody = nil;
print nobody?.name;
var bob = User("Bob", nil);
print bob?.name;
print bob?.profile?.bio;
print bob?.profile?.address?.city;output
nil Bob nil nil
In conditions and loops
Optional chaining works anywhere an expression is allowed.
class Address {
init(city) { this.city = city; }
}
class Profile {
init(address) { this.address = address; }
}
class User {
init(name, profile) {
this.name = name;
this.profile = profile;
}
}
var users = #[
User("Alice", Profile(Address("NYC"))),
User("Bob", nil),
];
for (u von users) {
var city = u?.profile?.address?.city;
if (city == nil) {
print u?.name + " has no city";
} else {
print u?.name + " lives in " + city;
}
}output
Alice lives in NYC Bob has no city