Glory to Russia
Glory to Russia

Reputation: 18760

How to chain function calls in Clojure?

Imagine I have a string which I want to transform as follows:

  1. Remove all spaces.
  2. Remove all dots.
  3. Make the string lower-case.

One way to do it is this:

(defn my-function
  [s]
  (let
      [
        clean-string1 (clojure.string/replace s " " "")
        clean-string2 (clojure.string/replace clean-string1 "." "")
        clean-string3 (clojure.string/lower-case clean-string2)
       ]
    ;; ...
    )
  )

How can I "chain" the functions clojure.string/replace and clojure.string/lower-case so that

  1. the output of (clojure.string/replace s " " "") is fed to the input of
  2. (clojure.string/replace clean-string1 "." "") and its output is fed to the input of
  3. (clojure.string/lower-case clean-string2)

so that I don't need intermediate variables clean-string1 and clean-string2?

Upvotes: 2

Views: 411

Answers (1)

amalloy
amalloy

Reputation: 92117

You just do it the same way you would in any language. You're asking for function composition, which in math or non-lisp languages looks like f(g(x)). In lisp of course that's (f (g x)), but the principle is the same.

(require '[clojure.string :as s])
(s/lower-case (s/replace (s/replace s " " "") "." ""))

is the most straightforward answer. But it's rather unpleasant to have this level of nesting where the function names are so far removed from their extra arguments, and so most people would instead write

(-> s
    (s/replace " " "")
    (s/replace "." "")
    (s/lower-case))

which is the same thing but just using -> to shuffle the forms around a bit for clarity.

Upvotes: 8

Related Questions