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.