diff --git a/docs/language/core.rst b/docs/language/core.rst index f18eedf..a05979e 100644 --- a/docs/language/core.rst +++ b/docs/language/core.rst @@ -534,9 +534,9 @@ nth Usage: ``(nth coll n)`` -Return the `nth` item in a collection, counting from 0. Unlike -``get``, ``nth`` works on both iterators and iterables. Raises ``IndexError`` -if the `n` is outside the range of ``coll`` or ``ValueError`` if it's negative. +Return the `nth` item in a collection, counting from 0. Return ``nil`` +if out of bounds (unless specified otherwise). Raise ``ValueError`` if +``n`` is negative. .. code-block:: hy @@ -546,14 +546,21 @@ if the `n` is outside the range of ``coll`` or ``ValueError`` if it's negative. => (nth [1 2 4 7] 3) 7 - => (nth [1 2 4 7] 5) - Traceback (most recent call last): - ... - IndexError: 5 + => (nil? (nth [1 2 4 7] 5)) + True + + => (nth [1 2 4 7] 5 "default") + 'default' => (nth (take 3 (drop 2 [1 2 3 4 5 6])) 2)) 5 + => (nth [1 2 4 7] -1) + Traceback (most recent call last): + ... + ValueError: Indices for islice() must be None or an integer: 0 <= x <= sys.maxsize. + + .. _numeric?-fn: numeric? diff --git a/hy/core/language.hy b/hy/core/language.hy index cb04eea..bc5587a 100644 --- a/hy/core/language.hy +++ b/hy/core/language.hy @@ -270,11 +270,10 @@ (import numbers) (instance? numbers.Number x)) -(defn nth [coll index] - "Return nth item in collection or sequence, counting from 0" - (try - (next (drop index coll)) - (catch [e StopIteration] (raise (IndexError index))))) +(defn nth [coll n &optional [default nil]] + "Return nth item in collection or sequence, counting from 0. + Return nil if out of bounds unless specified otherwise." + (next (drop n coll) default)) (defn odd? [n] "Return true if n is an odd number" diff --git a/tests/native_tests/core.hy b/tests/native_tests/core.hy index a4042b6..2f858ce 100644 --- a/tests/native_tests/core.hy +++ b/tests/native_tests/core.hy @@ -30,6 +30,9 @@ (defn assert-equal [x y] (assert (= x y))) +(defn assert-nil [x] + (assert (is x nil))) + (defn test-coll? [] "NATIVE: testing coll?" (assert-true (coll? [1 2 3])) @@ -390,13 +393,17 @@ "NATIVE: testing the nth function" (assert-equal 2 (nth [1 2 4 7] 1)) (assert-equal 7 (nth [1 2 4 7] 3)) - (try (do (nth [1 2 4 7] 5) (assert False)) - (catch [e [IndexError]] nil)) + (assert-nil (nth [1 2 4 7] 5)) + (assert-equal (nth [1 2 4 7] 5 "some default value") + "some default value") ; with default specified (try (do (nth [1 2 4 7] -1) (assert False)) (catch [e [ValueError]] nil)) ;; now for iterators (assert-equal 2 (nth (iter [1 2 4 7]) 1)) (assert-equal 7 (nth (iter [1 2 4 7]) 3)) + (assert-nil (nth (iter [1 2 4 7]) 5)) + (assert-equal (nth (iter [1 2 4 7]) 5 "some default value") + "some default value") ; with default specified (try (do (nth (iter [1 2 4 7]) -1) (assert False)) (catch [e [ValueError]] nil)) (assert-equal 5 (nth (take 3 (drop 2 [1 2 3 4 5 6])) 2))) diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index cc104fa..7f3ba54 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -495,9 +495,11 @@ (setv output (list (gen))) (assert (= [1] output))) + (defn test-first [] "NATIVE: test firsty things" (assert (= (first [1 2 3 4 5]) 1)) + (assert (is (first []) nil)) (assert (= (car [1 2 3 4 5]) 1)))