example/type.tuple.primi

Summary

Maintainability
Test Coverage
import ._helpers: assert_error

//
// Using tuples.
//

_ = "Default value for tuple is ()"
default = tuple()
assert(default == (), _)

//
// Tuples are immutable.
//

this_is_a_tuple = tuple([1, 'b', true])
assert_error(() => { this_is_a_tuple[] = 'forbidden'; })
assert_error(() => { this_is_a_tuple[1] = 'also forbidden'; })
assert_error(() => { this_is_a_tuple[999] = 'also forbidden'; })
assert_error(() => { this_is_a_tuple['what'] = 'also forbidden'; })

//
// Tuple literals.
//

this_is_not_tuple = (1)

_ = "Simple (x) literal is not a tuple, but 'x' as expected"
assert(this_is_not_tuple == 1, _)

some_tuple = (1,)
_ = "A literal (x,) with comma is a valid tuple literal"
assert(type(some_tuple) == tuple, _)

another_tuple = (1, 2)
_ = "A literal (x, y) without comma is also a valid tuple literal"
assert(type(some_tuple) == tuple, _)

another_tuple_alternative = (1, 2,)
_ = "If there are more items in the tuple literal, the comma is still allowed"
assert(type(another_tuple_alternative) == tuple, _)

//
// Tuple constructor - takes no argument or some iterable.
//

some_tuple = tuple()
assert(len(some_tuple) == 0)

iterable = [1, 2, 3, "x", "y", "z"]
some_tuple = tuple(iterable)
assert(len(some_tuple) == 6)
assert(some_tuple[-1] == "z")

// String are also iterable.
iterable = "stuff!"
some_tuple = tuple(iterable)
assert(len(some_tuple) == 6)
assert(some_tuple == ("s", "t", "u", "f", "f", "!"))

//
// Tuple comparisons.
//

tuple_a = (1,)
tuple_b = (1, 2) // Same as tuple_c
tuple_c = (1, 2) // Same as tuple_b
tuple_d = (2, 1)

assert(tuple_a != tuple_b)

_ = "Two separate tuple literals with same items are equal"
assert(tuple_b == tuple_c, _)

_ = "When comparing tuples, order of items is important"
assert(tuple_c != tuple_d, _)

//
// Tuple truthiness.
//

_ = "Only empty tuple is evaluated to false"
assert(bool(tuple()) == false, _)
assert(bool((true,)) == true)
assert(bool((false,)) == true)
assert(bool((false, true)) == true)
assert(bool((0,)) == true)
assert(bool((0, 1)) == true)

//
// Tuple operations.
//

// Getting length.

assert(len(tuple_a) == 1)
assert(len(tuple_b) == 2)

// Index access.

large_tuple = (1, "something", 234, true, null, ["wow", "a", "list"], false)
assert(len(large_tuple) == 7)

assert(large_tuple[0] == 1)
assert(large_tuple[1] == "something")
assert(large_tuple[3] == true)
assert(large_tuple[5] == ["wow", "a", "list"])

// Index access - via negative index.

assert(large_tuple[-1] == false)
assert(large_tuple[-2] == ["wow", "a", "list"])

// Iterating over tuples.

collector = []
for (item in large_tuple) {
    collector.push(item)
}

assert(len(collector) == 7)
assert(collector[0] == 1)
assert(collector[1] == "something")
assert(collector[3] == true)
assert(collector[5] == ["wow", "a", "list"])

// Tuples can be used as dict keys - because they are immutable and thus
// are "hashable". But they must not contain "unhashable" items (eg. lists,
// which are mutable and thus "unhashable") when used as dict keys.
small_tuple = (1, "something", 234, true, null)

some_dict = {
    small_tuple: "YAY",
    (1, 2, 3): "IMMUTABLES",
}

assert(some_dict[small_tuple] == "YAY")
assert(some_dict[(1, "something", 234, true, null)] == "YAY")
assert(some_dict[(1, 2, 3)] == "IMMUTABLES")

//
// Tuple membership.
//

assert("something" in large_tuple)
assert("not there" not in large_tuple)
assert(true in large_tuple)
assert(false in large_tuple)
assert(["wow", "a", "list"] in large_tuple)
assert(["wow", "a", "different", "list"] not in large_tuple)