Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructuring function arguments in Clojure

Tags:

clojure

I'm running an example in Clojure Programming by Chas Emerick et al.:

(defn make-user
  [& [uid]]
  {:user-id (or uid (str (java.util.UUID/randomUUID)))})

output:

=> (make-user "T-800")

{:user-id "T-800"}

Now I remove the square brackets around uid in line 2:

(defn make-user
  [& uid]
  {:user-id (or uid (str (java.util.UUID/randomUUID)))})

The evaluation result becomes:

=> (make-user "T-800")

{:user-id ("T-800")}

How to understand this difference?

like image 218
Pauli Avatar asked Jul 12 '26 05:07

Pauli


1 Answers

In an argument declaration, putting arguments next to & causes them to get wraped into a list.

(defn return [x y & more]
  [x y more])

(return 1 2 3 4 5 6)
;=> [1 2 (3 4 5 6)]

This wraping is useful to manipulate an undetermined number of args in a function:

(defn plus [& more] (apply + more))

(plus 3 4)
;=> 7

(plus 3 4 5 6)
;=> 18

But if we know there will only be one element as the optional argument and want to directly access it, we could use first to extract it:

(defn make-user-1 [& uid] {:user-id (first uid)})
(make-user-1 "T-800")
;=> {:user-id "T-800"}

Or, we could simply unwrap the argument element by using destructuring!

(defn make-user-2 [& [uid]] {:user-id uid})
(make-user-2 "T-800")
;=> {:user-id "T-800"}

So, here are some arg declaration and their given output:

(defn f [arg]     arg) ;=> arg
(defn f [& arg]   arg) ;=> (arg)
(defn f [& [arg]] arg) ;=> arg

The more you wrap args in the arg declaration, the more those unwrap in the body.

like image 142
leontalbot Avatar answered Jul 13 '26 20:07

leontalbot



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!