Skip to content

Commit 70c2628

Browse files
committed
update README and llist tests
1 parent f985336 commit 70c2628

2 files changed

Lines changed: 24 additions & 1 deletion

File tree

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1302,7 +1302,21 @@ Iterators are supported to walk over linked lists (this also gives tuple unpacki
13021302

13031303
But linked lists are not sequences, so e.g. Python's builtin ``reversed`` doesn't work on them. This also implies ``foldr`` (as implemented in ``unpythonic``) won't accept linked lists. If you need to right-fold a linked list, ``lreverse`` it and then left-fold that.
13041304

1305-
See `unpythonic.llist` for details.
1305+
Cons structures can be pickled.
1306+
1307+
For more, see `unpythonic.llist`.
1308+
1309+
#### Notes
1310+
1311+
There is no ``copy`` method or ``lcopy`` function, because cons cells are immutable; which makes cons structures immutable.
1312+
1313+
(However, for example, it is possible to `cons` a new item onto an existing linked list; that's fine because it produces a new cons structure - which shares data with the original, just like in Racket.)
1314+
1315+
In general, copying cons structures can be error-prone. Given just a starting cell it is impossible to tell if a given instance of a cons structure represents a linked list, or something more general (such as a binary tree) that just happens to locally look like one, along the path that would be traversed if it was indeed a linked list.
1316+
1317+
The linked list iteration strategy does not recurse in the ``car`` half, which could lead to incomplete copying. The tree strategy that recurses on both halves, on the other hand, is not safe to use on linked lists, because if the list is long, it will cause a stack overflow (due to lack of TCO in Python). With the tools in this library it would be possible to make a tree recurser with TCO applied in the `cdr` half, but the current generator-based implementation of ``BinaryTreeIterator`` is much shorter.
1318+
1319+
**Caution**: the ``nil`` singleton is freshly created in each session; newnil is not oldnil, so don't pickle a standalone ``nil``. The unpickler of ``cons`` automatically refreshes any ``nil`` instances inside a pickled cons structure, so that **cons structures** support the illusion that ``nil`` is a special value like ``None`` or ``...``. After unpickling, ``car(c) is nil`` and ``cdr(c) is nil`` still work as expected, even though ``id(nil)`` has changed.
13061320

13071321

13081322
### ``def`` as a code block: ``@call``

unpythonic/llist.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,15 @@ def test():
310310
# should iterate without crashing, since the nil is converted.
311311
assert tuple(k) == (1, 2, 3)
312312

313+
# cons structures are immutable (because cons cells are),
314+
# but new instances based on existing ones are ok.
315+
l1 = ll(3, 2, 1)
316+
l2 = cons(4, l1)
317+
assert l1 == ll(3, 2, 1)
318+
assert l2 == ll(4, 3, 2, 1)
319+
l3 = cons(6, cdr(l1))
320+
assert l3 == ll(6, 2, 1)
321+
313322
print("All tests PASSED")
314323

315324
if __name__ == '__main__':

0 commit comments

Comments
 (0)