Today’s a palindrome redux – a slimmer version of palindrome? function with reduce

After some tinkering with the palindrome? function I presented in the previous blog post I received a bunch of very educative responses that ultimately guided me to the following slimmer version of the palindrome? function.

(defn palindrome? [s]
  (= s (reduce #(str %2 %) s)))

(is (palindrome? "21022012"))

There’s no map function, but the point was to have it if it could improve the function.

I could also find traces to java.lang.StringBuffer.reverse() which “causes this character sequence to be replaced by the reverse of the sequence”, but the variation of the palindrome? function is certainly not shorter and moreover I don’t think it’s even prettier.

UPDATE on 02/24: The function changed after the comment of Denis where he pointed out the excessive parens around .reverse and str functions. The palindrome? function is now slightly improved.

UPDATE on 02/24: The function changed after the comment of Nander where he pointed out to use java.lang.StringBuilder as “This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations”.

(defn palindrome? [s]
  (= s (-> (StringBuilder. s)
           .reverse
           str)))

Note the space between the dot and “reverse” in (. reverse) (the line 2). You could have the s-expression with and without the space (!)

Looking at clojure.string/reverse doesn’t reveal anything better, either.

(defn ^String reverse
  "Returns s with its characters reversed."
  {:added "1.2"}
  [^CharSequence s]
  (.toString (.reverse (StringBuilder. s))))

I’d say it’s even uglier with the (.toString) call, at least length-wise. Could it be that using Java methods is faster than their Clojure counterparts?

I’d like to thank Mark, Andrew, Craig, Norman, Si Yu and Manuel for their inspirational comments, and tweets from Sean and Neale. You guys helped me a lot to get closer to functional programming zen in Clojure :) It matters a lot to me! As I’m presenting Clojure during Java conferences in Poland, the more I feel comfortable with the language the better presentation I’m to run. Thanks!

Be Sociable, Share!
This entry was posted in Languages.

6 Responses to Today’s a palindrome redux – a slimmer version of palindrome? function with reduce

  1. Denis says:

    You can use reverse and str without parens, as thrush macro will automatically add them on functions with single parameter, so your sample can be:

    (defn palindrome? [s]
      (= s (-> (StringBuffer. s) .reverse str)))
  2. Nandor Kracser says:

    You could change the StringBuffer to StringBuilder for better performance, because StringBuilder is non-threadsafe, so no locking is performed. See clojure.string/reverse.

  3. Ulrik Sandberg says:

    I would write it like this:

    (defn palindrome? [s] (= (seq s) (reverse s)))

    A quick test with a million iterations suggests that it's about twice as fast as your version.

    • The idea was to use map, reduce and filter functions as often as it could be advisable. I didn’t mean to write a highly performant variant of palindrome?. It was merely for educational purposes.

Leave a Reply

%d bloggers like this: