Clojure: Partial Function (Currying)

By Xah Lee. Date: . Last updated: .

partial is for creating a new function with a pre-filled argument(s) of a given function.

partial is a function that decompose a function by pre-fill n count its parameters. It returns a function g. When g is called with no arguments, it is equivalent to calling ƒ with n args. When g is given args, they are feed to ƒ starting with the unfilled args.

clojure.core/partial

Let's use math notation here.

Suppose you have a function ƒ that takes 3 args. You have:

ƒ[x, y, z]

when you call

partial[ƒ,a]

it returns a function, let's call it g.

When g is invoked

g[]

is equivalent to

ƒ[a]

All together, it's this:

(partial[ƒ,a])[] = ƒ[a]

if g is given args, it is feed to ƒ, starting with ƒ's second arg. That is,

(partial[ƒ,a])[] = ƒ[a]
(partial[ƒ,a])[b] = ƒ[a,b]
(partial[ƒ,a])[b,c] = ƒ[a,b,c]

If partial is given more args, it consumes more args from ƒ.

(partial[ƒ,a,b])[] = ƒ[a,b]
(partial[ƒ,a,b])[x1] = ƒ[a,b,x1]
(partial[ƒ,a,b])[x1,x2] = ƒ[a,b,x1,x2]

Let's use Clojure for example.

Suppose your function f[a,b,c] takes 3 args.

(defn f
  "join one or more strings"
  [& args]
  (apply str args))

(f "a" "b" "c") ; ⇒ "a b c"

;; define g. To be partial of f, feeding it 3 as first arg
(def g (partial f "3"))

(g) ; ⇒ "3"

(g "4") ; ⇒ "34"

Function Composition

Takes a set of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc.

;; example of compose

(defn f1 "append 1 to string x" [x] (str x "1"))
(defn f2 "append 2 to string x" [x] (str x "2"))
(defn f3 "append 3 to string x" [x] (str x "3"))

(f1 "a") ; "a1"

(def g (comp f3 f2 f1 ))

(g "x") ; "x123"

(g "a" "x")
;; 1. Unhandled clojure.lang.ArityException
;;    Wrong number of args (2) passed to: user/f1

;; because f1 only takes 1 arg

clojure.core/comp

Apply

Applies fn f to the argument list formed by prepending intervening arguments to args.

clojure.core/apply

;; example of apply

;; apply just takes all of its args, and feed to the function as multiple args, like unwrap the bracket

(apply str ["a" "b"]) ; "ab"

(apply str "1" ["a" "b"]) ; "1ab"

(apply str "1" "2" ["a" "b"]) ; "12ab"

;; here's what str does

;; str takes 1 or more args of string, and return a joined string
(str "a" "b") ; "ab"

;; can be just 1 arg
(str "a" ) ; "a"

;; if arg is not a string, it's converted to string
(str "a"  ["a" "b"]) ; "a[\"a\" \"b\"]"

(str "a" 1) ; "a1"

Misc

(trampoline f args) call f with args. If it returns a function, call it again (with no args). Repeat until it returns a value that is not a function, return that value. clojure.core/trampoline

(constantly x)→ Returns a function that takes any number of arguments and returns x. clojure.core/constantly

(complement f)→ Takes a fn f and returns a fn that takes the same arguments as f, has the same effects, if any, and returns the opposite truth value. clojure.core/complement

(memoize f)→ Returns a memoized version of a referentially transparent function. The memoized version of the function keeps a cache of the mapping from arguments to results and, when calls with the same arguments are repeated often, has higher performance at the expense of higher memory use. clojure.core/memoize