diff --git a/docs/language/core.rst b/docs/language/core.rst index f18eedf..0f0f91c 100644 --- a/docs/language/core.rst +++ b/docs/language/core.rst @@ -822,6 +822,32 @@ Raises ``ValueError`` if ``n`` is negative. => (list (drop 6 [1 2 3 4 5])) [] + +.. _drop-last-fn: + +drop-last +--------- + +Usage: ``(drop-last n coll)`` + +Return an iterator of all but the last ``n`` items in ``coll``. Raise ``ValueError`` if ``n`` is negative. + +.. code-block:: hy + + => (list (drop-last 5 (range 10 20))) + [10, 11, 12, 13, 14] + + => (list (drop-last 0 (range 5))) + [0, 1, 2, 3, 4] + + => (list (drop-last 100 (range 100))) + [] + + => (import itertools) + => (list (take 5 (drop-last 100 (itertools.count 10)))) + [10, 11, 12, 13, 14] + + .. _drop-while-fn: drop-while diff --git a/hy/core/language.hy b/hy/core/language.hy index cb04eea..9386558 100644 --- a/hy/core/language.hy +++ b/hy/core/language.hy @@ -57,7 +57,6 @@ (and (instance? (type :foo) k) (.startswith k (get :foo 0)))) - (defn dec [n] "Decrement n by 1" (_numeric-check n) @@ -119,6 +118,12 @@ "Drop `count` elements from `coll` and yield back the rest" (itertools.islice coll count nil)) +(defn drop-last [n coll] + "Return a sequence of all but the last n elements in coll." + (let [[iters (itertools.tee coll)]] + (map first (apply zip [(get iters 0) + (drop n (get iters 1))])))) + (defn empty? [coll] "Return True if `coll` is empty" (= 0 (len coll))) @@ -354,7 +359,7 @@ (def *exports* '[butlast calling-module-name coll? cons cons? cycle - dec distinct disassemble drop drop-while empty? even? + dec distinct disassemble drop drop-last drop-while empty? even? every? first filter filterfalse flatten float? gensym identity inc input instance? integer integer? integer-char? interleave interpose iterable? iterate iterator? keyword? list* diff --git a/tests/native_tests/core.hy b/tests/native_tests/core.hy index a4042b6..3dc8c13 100644 --- a/tests/native_tests/core.hy +++ b/tests/native_tests/core.hy @@ -117,6 +117,19 @@ (setv res (list (take 5 (drop 2 (iterate inc 0))))) (assert-equal res [2 3 4 5 6])) +(defn test-drop-last [] + "NATIVE: testing drop-last function" + (assert-equal (list (drop-last 5 (range 10 20))) + [10 11 12 13 14]) + (assert-equal (list (drop-last 0 (range 5))) + [0 1 2 3 4]) + (assert-equal (list (drop-last 100 (range 100))) + []) + ; with an infinite sequence + (import itertools) + (assert-equal (list (take 5 (drop-last 100 (itertools.count 10)))) + [10 11 12 13 14])) + (defn test-drop-while [] "NATIVE: testing drop-while function" (setv res (list (drop-while even? [2 4 7 8 9])))