Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
CLJ-2822: Add RT.nthImpl
* Add `RT.nthImpl` which accepts an `Object n` instead of `int n`, and throws an `UnsupportedOperationException` before casting.
* Change `clojure.core/nth` to call `RT.nthImpl`.
  • Loading branch information
NoahTheDuke committed Sep 26, 2025
commit 99510c12b5935c25caa8a5aa4d3f488e54c12985
6 changes: 3 additions & 3 deletions src/clj/clojure/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -893,11 +893,11 @@
bounds, nth throws an exception unless not-found is supplied. nth
also works for strings, Java arrays, regex Matchers and Lists, and,
in O(n) time, for sequences."
{:inline (fn [c i & nf] `(. clojure.lang.RT (nth ~c ~i ~@nf)))
{:inline (fn [c i & nf] `(. clojure.lang.RT (nthImpl ~c ~i ~@nf)))
:inline-arities #{2 3}
:added "1.0"}
([coll index] (. clojure.lang.RT (nth coll index)))
([coll index not-found] (. clojure.lang.RT (nth coll index not-found))))
([coll index] (. clojure.lang.RT (nthImpl coll index)))
([coll index not-found] (. clojure.lang.RT (nthImpl coll index not-found))))

(defn <
"Returns non-nil if nums are in monotonically increasing order,
Expand Down
30 changes: 30 additions & 0 deletions src/jvm/clojure/lang/RT.java
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,24 @@ static public Object nth(Object coll, int n){
return nthFrom(Util.ret1(coll, coll = null), n);
}

static int castNthIdx(Object o) {
if (o instanceof Number) {
return intCast(o);
}
throw new UnsupportedOperationException(
"nth idx not supported on this type: " + o.getClass().getSimpleName());
}

/**
* Only for use in `clojure.core/nth`.
*/
static public Object nthImpl(Object coll, Object n){
int idx = castNthIdx(n);
if(coll instanceof Indexed)
return ((Indexed) coll).nth(idx);
return nthFrom(Util.ret1(coll, coll = null), idx);
}

static Object nthFrom(Object coll, int n){
if(coll == null)
return null;
Expand Down Expand Up @@ -960,6 +978,18 @@ static public Object nth(Object coll, int n, Object notFound){
return nthFrom(coll, n, notFound);
}

/**
* Only for use in `clojure.core/nth`.
*/
static public Object nthImpl(Object coll, Object n, Object notFound){
int idx = castNthIdx(n);
if(coll instanceof Indexed) {
Indexed v = (Indexed) coll;
return v.nth(idx, notFound);
}
return nthFrom(coll, idx, notFound);
}

static Object nthFrom(Object coll, int n, Object notFound){
if(coll == null)
return notFound;
Expand Down
10 changes: 10 additions & 0 deletions test/clojure/test_clojure/sequences.clj
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,16 @@
(is (thrown? IndexOutOfBoundsException (nth (java.util.ArrayList. []) -1))) ; ???
(is (thrown? IndexOutOfBoundsException (nth (java.util.ArrayList. [1 2 3]) -1))) ; ???

;; CLJ-2822
(is (thrown? UnsupportedOperationException (nth 1 [1 2 3])))
(is (try ^{:line 12345} (nth 1 [1 2 3])
(catch UnsupportedOperationException e
(let [line (->> (.getStackTrace e)
(drop-while #(= "clojure.lang.RT" (.getClassName ^StackTraceElement %)))
(first)
(#(.getLineNumber ^StackTraceElement %)))]
(= 12345 line)))))

(are [x y] (= x y)
(nth '(1) 0) 1
(nth '(1 2 3) 0) 1
Expand Down