Clojure: string interpolation

We have a URL with some placeholder values that we want to replace.



One way of doing this is to use str function.

(defn shop-url [seller item-code currency]
  (str "" seller
       "/items/"               item-code
       "/prices/"              currency))

(shop-url "bob" "A567" "EUR")

=> ""

There's nothing wrong with this solution. However, it does encapsulate/hide information that might be useful at the call site: order of arguments and what URL it is operating on.


Another approach would be to use the format function, which gives us string interpolation.

(format ""

=> ""

The downside of this is that the placeholders in the URL are not self-documenting.


What about using a string replace function? Clojure core does have functions for replacing matches in strings, but it doesn't have a built-in function for replacing multiple different matches. Let's see how we could implement our own replace-several function.

(defn replace-several [s & {:as replacements}]
  (reduce (fn [s [match replacement]]
            (clojure.string/replace s match replacement))
          s replacements))

(replace-several "$seller/items/$item-code/prices/$currency"
                 "$seller" "bob"
                 "$item-code" "A567"
                 "$currency" "EUR")

=> ""

The above works and reads better than our previous solutions as the value substitutions are clear. If you find the destructuring in the reduce a bit cumbersome you can use reduce-kv which returns the accumulator, key and values for us.

(defn replace-several [s & {:as replacements}]
  (reduce-kv clojure.string/replace s replacements))

Hopefully, these examples come in handy the next time you need some pseudo-string interpolation.