Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Values

A value is one of nil, a boolean, a number, a string, an array, an object, a function, a map or set, bytes, a struct or a stream. type names it:

print(type(nil));              // nil
print(type(42));               // number
print(type("ann"));            // string
print(type([1, 2]));           // array
print(type({ name: "ann" }));  // object
print(type(x => x * 2));       // function

Type Tests

v is T tests that v is of type T: a struct or enum type, or one of the built-in nil, boolean, number, string, array, object, function, map, set, bytes, stream, struct and enum, which are what type says of a struct type and an enum type themselves. It has the precedence of ==; the same test is name is T in match and catch e is T.

struct User { name }

print(42 is number);                  // true
print("42" is number);                // false
print([1, 2] is array);               // true
print(User { name: "ann" } is User);  // true
print(User { name: "ann" } is object); // false
print(nil is nil);                    // true
print(User is struct);                // true

A variable named like a built-in type hides it, and testing against anything but a type is a TypeError:

let string = "text";
print("a" is string); // TypeError: Right operand of 'is' must be a type, got string.

Truthiness

Falsy values are nil, false, 0 and ""; everything else, including empty arrays and objects, is truthy.

for v in [nil, false, 0, "", [], {}, "0"] {
    print("%q is %s".format(v, v ? "truthy" : "falsy"));
}
// nil is falsy
// false is falsy
// 0 is falsy
// "" is falsy
// [] is truthy
// {} is truthy
// "0" is truthy

So || gives a fallback for an empty string, and an empty array needs .len():

let user = { name: "ann", nickname: "" };
print(user.nickname || user.name);   // ann

let cart = [];
if cart { print("has a cart"); }     // has a cart
if cart.len() == 0 { print("cart is empty"); }  // cart is empty

Equality

== compares numbers (an integer with a float too), strings, bytes, booleans and nil by value, functions and streams by identity, and arrays, objects, maps and sets structurally (element by element, cycles included), so [1, 2] == [1, 2] is true. contains and indexOf use the same equality. Values of different types are never equal: 1 == "1" is false.

print(1 == 1.0);                                    // true
print([1, [2, 3]] == [1, [2, 3]]);                  // true
print({ role: "admin", tags: ["ops"] } == { tags: ["ops"], role: "admin" }); // true
print(1 == "1");                                    // false
print(nil == false);                                // false

let seen = [{ id: 1 }, { id: 2 }];
print(seen.contains({ id: 2 }));                    // true
print(seen.indexOf({ id: 2 }));                     // 1

let validate = order => order.qty > 0;
let check = validate;
print(check == validate);                           // true
print((order => order.qty > 0) == validate);        // false

Printing

print shows strings inside arrays and objects quoted, so ["1", 1] and [1, 1] look different; a string printed on its own is written as is. Objects print their keys in the order they were added.

print("1");                          // 1
print(["1", 1]);                     // ["1", 1]
print([nil, true, 2.5]);             // [nil, true, 2.5]
print({ name: "ann", age: 31 });     // {name: "ann", age: 31}