class BinaryTree function __construct(T, value) assert(type(T) == "string", "T must be the name of a class") assert(type(value) == T, "Value must be of type T.") self.kind = T self.value = value self.left = nil self.right = nil end -- Alternative constructor to enable kind to be inferred from type of value. static function of(value) return new BinaryTree(type(value), value) end function getKind() return self.kind end function getValue() return self.value end function getLeft() return self.left end function getRight() return self.right end function setValue(v) assert(type(v) == self.kind, $"Value must be of type {self.kind}") self.value = v end function setLeft(b) assert(b instanceof BinaryTree and b:getKind() == self.kind, $"Argument must be a BinaryTree of type {self.kind}") self.left = b end function setRight(b) assert(b instanceof BinaryTree and b:getKind() == self.kind, $"Argument must be a BinaryTree of type {self.kind}") self.right = b end function map(f) local tree = BinaryTree.of(f(self.value)) if self.left then tree:setLeft(self.left:map(f)) end if self.right then tree:setRight(self.right:map(f)) end return tree end function show_top_three() return $"({self.left:getValue()}, {self.value}, {self.right:getValue()})" end end local b = BinaryTree.of(6) b:setLeft (BinaryTree.of(5)) b:setRight(BinaryTree.of(7)) print(b:show_top_three()) local b2 = b:map(|i| -> i * 10) print(b2:show_top_three()) b2:setValue("six") -- generates an error because "six" is not a number