javaguy
javaguy

Reputation: 4432

Explaining this clojure syntax?

​​How​ to ​understand​ ​this ​​simple clojure code? I ​kind of ​understand​ what it is trying to do but can someone explain the syntax in great detail so I can confidently use it?

(map (fn [x] (.toUpperCase x)) (.split "Dasher Dancer Prancer" " "))

Upvotes: 0

Views: 238

Answers (2)

Chiron
Chiron

Reputation: 20245

From Clojure REPL:

(doc map)
clojure.core/map
([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]) Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments.

(.split "Dasher Dancer Prancer" " ") is generating a sequence of strings and each tokenized string will be passed to (fn [x] (.toUpperCase x))

However, (fn [x] (.toUpperCase x)) is too much unnecessary typing. You can do:

(map #(.toUpperCase %) (.split "Dasher Dancer Prancer" " "))

or:

(map (memfn toUpperCase) (.split "Dasher Dancer Prancer" " "))

Upvotes: 5

Charles Duffy
Charles Duffy

Reputation: 295403

This is defining a lambda (an anonymous function, which calls toUpperCase on its single argument), and applying it (using map) to each result of String.split().

map takes a function and a sequence of things to apply that function to, and returns a sequence of results from applying the function to the input sequence.

The following breaks the operation down into smaller pieces:

(defn upper-case-fn [^String x]
  "this makes the same function, but not anonymous, and provides a type hint
  (making it more efficient by avoiding the need for reflection)."
  (.toUpperCase x))

;; you could also write the above like so:
(def upper-case-fn (fn [x] (.toUpperCase x)))

(def input-seq
  "this assigns your input seq to a var; in the real world, with dynamic data,
   you wouldn't do this"
  (.split "Dasher Dancer Prancer" " "))

(def output-seq
  "this is precisely the same as your sample, except that it's using a named
  function rather than an anonymous one, and assigns the output to a var"
  (map upper-case-fn input-seq))

;; if you enter this at a repl, you're looking at the contents of this var
output-seq

Upvotes: 4

Related Questions