From 6d9d83f182008af66278f5ec63508a97e9900497 Mon Sep 17 00:00:00 2001 From: kaizeenn Date: Sat, 4 Jul 2026 12:48:40 +0700 Subject: [PATCH] fix: tail(0, seq) should return empty instead of the whole sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `tail(0, seq)` is implemented as `seq[-n:]` which for `n == 0` becomes `seq[-0:]` = `seq[0:]` — returning the entire sequence instead of the last zero elements. This also makes `tail` inconsistent across iterable types: sliceable inputs return the whole sequence, while non-sliceable iterables hit the `deque(seq, 0)` fallback and correctly return empty. Fix by handling `n == 0` as a special case, returning `seq[:0]` for sliceable types and `()` for non-sliceable iterables. Fixes #626. Signed-off-by: kaizeenn --- toolz/itertoolz.py | 5 +++++ toolz/tests/test_itertoolz.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/toolz/itertoolz.py b/toolz/itertoolz.py index 354ecf25..f8143345 100644 --- a/toolz/itertoolz.py +++ b/toolz/itertoolz.py @@ -332,6 +332,11 @@ def tail(n, seq): drop take """ + if n == 0: + try: + return seq[:0] + except (TypeError, KeyError): + return () try: return seq[-n:] except (TypeError, KeyError): diff --git a/toolz/tests/test_itertoolz.py b/toolz/tests/test_itertoolz.py index c8640917..f505153f 100644 --- a/toolz/tests/test_itertoolz.py +++ b/toolz/tests/test_itertoolz.py @@ -189,6 +189,11 @@ def test_tail(): assert list(tail(3, 'ABCDE')) == list('CDE') assert list(tail(3, iter('ABCDE'))) == list('CDE') assert list(tail(2, (3, 2, 1))) == list((2, 1)) + assert tail(0, [10, 20, 30]) == [] + assert list(tail(0, [10, 20, 30])) == [] + assert tuple(tail(0, iter([10, 20, 30]))) == () + assert tail(0, 'ABCDE') == '' + assert tail(0, (3, 2, 1)) == () def test_drop():