Skip to content

Commit 99a55e6

Browse files
authored
Cache sequence results (#102)
* Cache sequence results * Fix typechecking errors * Silence Pylint slots error
1 parent b54a652 commit 99a55e6

File tree

3 files changed

+23
-9
lines changed

3 files changed

+23
-9
lines changed

basilisp/lang/runtime.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,10 @@ def first(o):
353353
return None
354354
if isinstance(o, lseq.Seq):
355355
return o.first
356-
return to_seq(o).first
356+
s = to_seq(o)
357+
if s is None:
358+
return None
359+
return s.first
357360

358361

359362
def rest(o):
@@ -364,12 +367,12 @@ def rest(o):
364367
if isinstance(o, lseq.Seq):
365368
s = o.rest
366369
if s is None:
367-
return llist.List.empty()
370+
return lseq.empty()
368371
return s
369-
s = to_seq(o).rest
372+
s = to_seq(o)
370373
if s is None:
371-
return llist.List.empty()
372-
return s
374+
return lseq.empty()
375+
return s.rest
373376

374377

375378
def next(o): # pylint:disable=redefined-builtin

basilisp/lang/seq.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,23 +84,29 @@ class _Sequence(Seq[T]):
8484
8585
Do not directly instantiate a Sequence. Instead use the `sequence` function
8686
below."""
87-
__slots__ = ('_first', '_seq')
87+
__slots__ = ('_first', '_seq', '_rest')
8888

8989
def __init__(self, s: Iterator, first: T) -> None:
9090
self._seq = s # pylint:disable=assigning-non-slot
9191
self._first = first # pylint:disable=assigning-non-slot
92+
self._rest: Optional[Seq] = None # pylint:disable=assigning-non-slot
9293

9394
@property
9495
def first(self) -> T:
9596
return self._first
9697

9798
@property
9899
def rest(self) -> Optional["Seq[T]"]:
100+
if self._rest:
101+
return self._rest
102+
99103
try:
100104
n = next(self._seq)
101-
return _Sequence(self._seq, n)
105+
self._rest = _Sequence(self._seq, n) # pylint:disable=assigning-non-slot
102106
except StopIteration:
103-
return _EmptySequence()
107+
self._rest = _EmptySequence() # pylint:disable=assigning-non-slot
108+
109+
return self._rest
104110

105111
def cons(self, elem):
106112
return Cons(elem, self)

tests/seq_test.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,9 @@ def test_sequence():
2424
assert [1, 2, 3] == [e for e in lseq.sequence([1, 2, 3])]
2525
assert llist.l(1, 2, 3) == lseq.sequence([1, 2, 3])
2626
assert llist.l(1, 2, 3) == lseq.sequence(llist.l(1, 2, 3))
27-
assert llist.l(1, 2, 3) == llist.list(lseq.sequence([1, 2, 3]))
27+
assert llist.l(1, 2, 3) == llist.list(lseq.sequence([1, 2, 3]))
28+
29+
s = lseq.sequence([1, 2, 3])
30+
assert 2 == s.rest.first
31+
assert 3 == s.rest.rest.first
32+
assert None is s.rest.rest.rest.first

0 commit comments

Comments
 (0)