Welcome! Please see the About page for a little more info on how this works.

+3 votes
in Protocols by
retagged by

I like to use reduce-kv on vectors, where the k is the index and the v is the k-th element of the vector. IMHO, it would be convenient if reduce-kv could also work directly on a String. However, IKVReduce isn't implemented for String so that fails. You can use (vec "my-string") as a work-around, but maybe suffer a bit on performance.

I think something like this would work:

(extend-protocol clojure.core.protocols/IKVReduce
java.lang.String
(kv-reduce [^String s f init]
  (let [cnt (.length s)]
    (loop [i 0 res init]
      (if (< i cnt)
        (let [ret (f res i (.charAt s i))]
          (if (reduced? ret)
            @ret
            (recur (unchecked-inc i) ret)))
        res)))))

However, the guidelines say I shouldn't extend a protocol that I don't own to a type that I don't own.

By the way, (reduce conj [] "Foobar") works as you would expect because String implements clojure.core.protocols/InternalReduce so maybe that's a good precedent.

by
But on chars or codepoints? :)
by
Do whatever (nth "abc" 1) or (seq "abc") or (vec "abc") does now.  I think Character would be the normal expectation, but my experience is mostly with ASCII.  In my quick test, an emoji comes back as two Characters.   (map long (vec "")) returns (55357 56832).
by
My happy face emoji disappeared into an empty string but you get the idea.
by
i agree that it matching nth would be the most consistent.

1 Answer

0 votes
by
...