{:check ["true"], :rank ["defn" "fn" "anonymous" "references"]}

Index

More On Building Functions in Clojure

Defn

Defining functions

The most familiar (and common) way to define functions in Clojure is using the (defn ...) construct:

(defn <name> [ <param> ... ] 
    <body>)
In [3]:
(defn greeting [username]
    (str "Hello, " username "."))
Out[3]:
#'user/greeting
In [5]:
; Now we can use it.

(println (greeting "Albert Einstein"))
;
Hello, Albert Einstein.

Add documentation string

Clojure supports metadata such as docstring, associated with the function defined.

(defn <name>
    <doc string>
    [param ...]
    <body>)
In [22]:
(defn greeting
"Generate a greeting message as a string
for the given username."
    [username]
    (str "Hello, " username "."))
Out[22]:
#'user/greeting
In [23]:
; Now we can get some help on the function
(println (:doc (meta (var greeting))))
;
Generate a greeting message as a string
for the given username.
In [24]:
; We can still use the function as always.
(greeting "Albert Einstein")
Out[24]:
"Hello, Albert Einstein."

Multiple arities

Definition:

arity is the number of parameters a function can accept.

In [25]:
(defn greeting
"Generates a greeting message for the given username.
    
- No paramete: default message.
- username: message for the user.
- title username: message will refer to the user by the title."
    ([] "Hi there.")
    ([username] (str "Hello, " username "."))
    ([title username]
     (str "Hello, " title ". " username ".")))
Out[25]:
#'user/greeting
In [26]:
(println (:doc (meta (var greeting))))
;
Generates a greeting message for the given username.
    
- No paramete: default message.
- username: message for the user.
- title username: message will refer to the user by the title.
In [27]:
(greeting)
Out[27]:
"Hi there."
In [28]:
(greeting "Albert Einstein")
Out[28]:
"Hello, Albert Einstein."
In [29]:
(greeting "Prof" "Albert Einstein")
Out[29]:
"Hello, Prof. Albert Einstein."

Fn

Anonymous Functions

  1. Anonymous functions are functions that are created without given a name in the definition.

  2. We can always bind functions to symbols.

(fn [param ...] body)
In [1]:
(fn [username]
    (str "Hello, " username "."))
Out[1]:
#function[user/eval4096/fn--4097]

Invoking functions without names

  1. Use them in a form.
  2. Bind them to symbols, and use the symbols.
In [4]:
((fn [username] (str "Hello, " username ".")) "Albert Einstein")
Out[4]:
"Hello, Albert Einstein."
In [5]:
(let [f (fn [username] (str "Hello, " username "."))]
    (f "Albert Einstein"))
Out[5]:
"Hello, Albert Einstein."
In [6]:
; Note the symbol is only valid in the scope of `(let ...)`
(f "Albert Einstein")
Syntax error compiling at (REPL:2:1).
Unable to resolve symbol: f in this context
  Util.java:   221 clojure.lang.Util/runtimeException
   core.clj:  3214 clojure.core$eval/invokeStatic
   core.clj:  3210 clojure.core$eval/invoke
   main.clj:   437 clojure.main$repl$read_eval_print__9086$fn__9089/invoke
   main.clj:   458 clojure.main$repl$fn__9095/invoke
   main.clj:   368 clojure.main$repl/doInvoke
RestFn.java:  1523 clojure.lang.RestFn/invoke
   AFn.java:    22 clojure.lang.AFn/run
   AFn.java:    22 clojure.lang.AFn/run
Thread.java:   748 java.lang.Thread/run

Anonymous

Shorthand For Anonymous Functions

Clojure require so much of function construction that it has an even shorter hand to create anonymous functions.

#(body)
  1. % is the first argument.
  2. If more arguments are expected, use %1, %2, %3 etc.
In [10]:
#(str "Hello, " % ".")
Out[10]:
#function[user/eval4150/fn--4151]
In [11]:
(#(str "Hello, " % ".") "Albert Einstein")
Out[11]:
"Hello, Albert Einstein."
In [12]:
(let [f #(str "Hello, " % ".")]
    (f "Albert Einstein"))
Out[12]:
"Hello, Albert Einstein."

References

References

  1. Programming Clojure: Section 2.3