Companion code for the text. Each Python file can be downloaded and run on its
own; its docstrings include doctests (python3 -m doctest -v link.py).
Hog Two Ways¶
Hog Two Ways is a Gleam project that replaces the mutable dice functions of a Python Hog game with explicit state handling and with state passing. Download the whole project as dice.zip.
link.py¶
The Link data class for linked lists from
Section 2.3, with a __str__ method that
formats a linked list as its items within parentheses.
Source: link.py
link.py
from __future__ import annotations
from dataclasses import dataclass
type LinkedList[T] = Link[T] | tuple[()]
@dataclass
class Link[T]:
"""A Link has a first value of type T and the rest of the linked list.
The rest is either another Link or the empty tuple.
>>> s = Link(3, Link(4, Link(5)))
>>> s.first
3
>>> s.rest.first
4
>>> s.rest.rest.first
5
>>> s.rest.rest.rest is ()
True
>>> s
Link(first=3, rest=Link(first=4, rest=Link(first=5, rest=())))
>>> s.rest.rest
Link(first=5, rest=())
>>> print(s)
(3 4 5)
"""
first: T
rest: LinkedList[T] = () # rest defaults to an empty linked list
def __str__(self):
return format_link(self)
def format_link(s: Link):
"""Return a Link s formatted as items within parentheses."""
string = '(' + str(s.first)
remaining = s.rest
while isinstance(remaining, Link):
string += ' ' + str(remaining.first)
remaining = remaining.rest
assert remaining == (), f'{s!r} is not a LinkedList'
return string + ')'
tree.py¶
The Tree data class from Section 2.3, with a
__str__ method that prints each branch indented below its label.
Source: tree.py
tree.py
from __future__ import annotations
from dataclasses import dataclass, field
@dataclass
class Tree[T]:
"""A Tree has a label (of type T) and a list of branches, which are trees.
>>> t = Tree(3, [Tree(1, []), Tree(2, [Tree(1, []), Tree(1, [])])])
>>> t.branches[0]
Tree(label=1, branches=[])
>>> len(t.branches)
2
>>> t.branches[1].label
2
>>> len(t.branches[1].branches)
2
>>> expr = Tree(10, [Tree(6, [Tree(2), Tree('*'), Tree(3)]), Tree('+'), Tree(4)])
>>> print(expr)
10
6
2
*
3
+
4
"""
label: T
branches: list[Tree[T]] = field(default_factory=list) # branches defaults to []
def __str__(self):
return format_tree(self)
def format_tree(t: Tree, indent='') -> str:
"Format a tree with each branch indented below its label."
assert isinstance(t, Tree), f'{t!r} is not a Tree'
assert isinstance(t.branches, list), f'branches of {t!r} is not a list'
string = indent + str(t.label)
for b in t.branches:
string += '\n' + format_tree(b, indent + ' ')
return string