Sometimes a value might not exist. Your friend might not have a nickname. A search through a list might not find anything. A game character might not be holding an item. Programs need a way to say "there's nothing here", and steav2 has one: sone.
sone: nothing at all
sone means nothing (programmers often call this "nil" or "null"). But steav2 is careful with it: an ordinary variable can never be sone. A LekKut is always a real number, an Ahsor is always real text.
bongSlanhOun "nothing";
akthe score: LekKut = sone; [line 2] Error at 'sone': expected LekKut but got sone That's a good thing! It means that when you have a LekKut, you never have to worry that it's secretly empty.
Optionals: T?
When a value really might be missing, you say so by adding a question mark to its type. Ahsor? means "maybe some text, maybe sone". This is called an optional type. (In docs you'll see T?, where T stands for any type.)
bongSlanhOun "nickname";
akthe nickname: Ahsor? = sone;
jongyeytha nickname;
nickname = "Bo";
jongyeytha nickname; sone
Bo An optional box can hold either a real value or sone, and you can switch between them whenever you like.
Checking before you use it
Because an optional might be sone, steav2 won't let you use it as if it were definitely there:
bongSlanhOun "careless";
sampoan Pet {
akthe name: Ahsor;
}
akthe lostPet: Pet? = sone;
jongyeytha lostPet.name; [line 6] Error at 'name': this is Pet?, it might be sone: check it with ber (x != sone) first The error tells you exactly what to do. Check with ber (x != sone), and inside that block, steav2 knows the value is really there, so you can use it like a normal value:
bongSlanhOun "careful";
sampoan Pet {
akthe name: Ahsor;
}
akthe foundPet: Pet? = Pet("Mew");
ber (foundPet != sone) {
jongyeytha "Found " + foundPet.name + "!";
} minjengte {
jongyeytha "Still looking.";
} Found Mew! This also works the other way round: in the minjengte of a ber (x == sone), the value is known to be there.
bongSlanhOun "greeting";
akthe nickname: Ahsor? = "Bo";
ber (nickname == sone) {
jongyeytha "Hello, stranger!";
} minjengte {
jongyeytha "Hey " + nickname + "!";
} Hey Bo! Functions that might not find anything
Optionals are perfect for a function's answer when there sometimes isn't one. Here's a function that searches an array and returns the position of a word, or sone if the word isn't there:
bongSlanhOun "search";
rupamun find(words: [Ahsor], wanted: Ahsor) -> LekKut? {
somhab (akthe i: LekKut = 0; i < words.len(); i += 1) {
ber (words[i] == wanted) {
morvenh i;
}
}
morvenh sone;
}
akthe menu = ["rice", "noodles", "soup"];
akthe spot = find(menu, "noodles");
ber (spot != sone) {
jongyeytha "noodles are dish number " + (spot + 1);
}
jongyeytha find(menu, "pizza"); noodles are dish number 2
sone Notice that morvenh i; returns a plain LekKut, and that's fine: a real value can always go into a LekKut? box. And inside ber (spot != sone), spot is a plain LekKut, so spot + 1 works.
Your turn
- Make an
akthe favouriteColor: Ahsor? = sone;and printNo favourite yetif it'ssone, orI love ...with the colour otherwise. Then set it and try again. Hint:ber (favouriteColor == sone). - Write
firstLong(words: [Ahsor]) -> Ahsor?that returns the first word that isn't"a"or"the", orsoneif there isn't one. - Write
safeDivide(a: LekKut, b: LekKut) -> LekKut?that returnssonewhenbis0, anda / botherwise.
Solution for exercise 3:
bongSlanhOun "safe divide";
rupamun safeDivide(a: LekKut, b: LekKut) -> LekKut? {
ber (b == 0) {
morvenh sone;
}
morvenh a / b;
}
jongyeytha safeDivide(10, 2);
jongyeytha safeDivide(10, 0); 5
sone