What is meant by destructuring in Clojure? - clojure

I'm a Java and learning clojure.
What is exactly destructuring in clojure?
I can see this blog saying:
The simplest example of destructuring is assigning the values of a
vector.
user=> (def point [5 7])
#'user/point
user=> (let [[x y] point]
(println "x:" x "y:" y))
x: 5 y: 7
what he meant by assigning the values of a vector? Whats the real use of it?
Thanks in advance

point is a variable that contains a vector of values. [x y] is a vector of variable names.
When you assign point to [x y], destructuring means that the variables each get assigned the corresponding element in the value.
This is just a simpler way of writing:
(let [x (nth point 0) y (nth point 1)]
(println "x:" x "y:" y))
See Clojure let binding forms for another way to use destructuring.

It means making a picture of the structure of some data with symbols
((fn [[d [s [_ _]]]]
(apply str (concat (take 2 (name d)) (butlast (name s)) (drop 7 (name d))) ))
'(describing (structure (of data))))
=> "destructuring"
((fn [[d e _ _ _ _ _ i n g _ _ _ _ _ s t r u c t u r e & etc]]
[d e s t r u c t u r i n g]) "describing the structure of data")
=> [\d \e \s \t \r \u \c \t \u \r \i \n \g]
Paste those ^ examples into a REPL & play around with them to see how it works.

The term "Destructuring" sounds heavier than it is.
It's like visually matching shapes to shapes. For example:
(def nums [1 2 3 4 5 6])
(let [[a b c & others] nums]
;; do something
)
Imagine the effect of the let binding as:
1 2 3 4 5 6
| | | ( )
v v v v
[a b c & others]
;; Now we can use a, b, c, others, and of course nums,
;; inside the let binding:
user=> (let [[a b c & others] nums]
(println a)
(println b)
(println c)
(println others)
(println nums))
1
2
3
(4 5 6)
[1 2 3 4 5 6]
The goal is to concisely name items of a collection, for use inside the scope of a let binding or function (i.e. within a "lexical scope").
Why "concise"? Well, without destructuring, the let binding would look like this:
(let [a (nth nums 0) ;; or (first nums)
b (nth nums 1) ;; or (second nums)
c (nth nums 2)
others (drop 3 nums)]
;; do something
)
This illustrates the basic idea. There are many details (ifs and buts, and dos and don'ts), and it's worth reading further, in depth. Here are a few resources that explain more, with examples:
My personal favourite: Jay Fields's post on Clojure Destructuring:
http://blog.jayfields.com/2010/07/clojure-destructuring.html
A gentle introduction to destructuring, from Braveclojure:
http://www.braveclojure.com/do-things/#3_3_3__Destructuring

its used to name components of a data structure, and get their values.
Say you want to have a "person" structure. In java, you would go all the way to create a class with constructors, getters and setters for the various fields, such as name, age, height etc.
In Clojure you could skip the "ceremony" and simply have a vector with 3 slots, first for name, than for age and last for height. Now you could simply name these "components" and get their values, like so:
(def person ["Fred" 30 180])
(let [[name age height] person]
(println name age height)) ;; will print: Fred 30 180
p.s - there are better ways to make a "person" in clojure (such as records etc), this is just an example to understand what destructuring does.

Destructuring is a convenience feature which allows local bindings (not variables!) to be created easily by taking apart complex data structures (seq-ables like vectors, or associatives like hash-maps), as it is described here.
Take the following example:
(let [v [1 2 3 4 5 6]
v_0 (first v)
v_1 (nth v 1)
v_rest (drop 2 v)
m {:a 1 :b 2}
m_a (get m :a)
m_b (get m :b)
m_default (get m :c "DEFAULT")]
(println v, v_0, v_1, v_rest, m, m_a, m_b, m_default))
Then the above code can be simplified using destructuring bindings like the following:
(let [[v_0 v_1 & v_rest :as v]
[1 2 3 4 5 6]
{m_a :a m_b :b m_default :c :or {m_default "DEFAULT"} :as m}
{:a 1 :b 2}]
(println v, v_0, v_1, v_rest, m, m_a, m_b, m_default))
Destructuring patterns can be used in let bindings and function parameters (fn, defn, letfn, etc.), and also in macros to return let bindings containing such destructuring patterns.
One important usage to note is with the if-letand when-let macros. The if statement is always evaluated on the whole form, even if the destructured bindings themselves evaluate to nil:
(if-let [{:keys [a b]}
{:c 1 :d 2}]
(println a b)
(println "Not this one"))

Destructuring binds a pattern of names to a complex object by binding each name to the corresponding part of the object.
To bind to a sequence, you present a vector of names. For example ...
(let [[x y] (list 5 7)] ... )
... is equivalent to
(let [x 5, y 7] ... )
To bind to a map or to a vector by index lookup, you present a map of name-to-key pairs. For example ...
(let [{x 0, y 1} [5 7]] ... )
... is equivalent to both of the above.
As others have mentioned, you can find a full description of this powerful mechanism here.

Related

Get Clojure argument list

I want something that gives me the sequence of actual values passed to a function, similar to the arguments value in a javascript function.
I am aware that I can grab the entire function argument list using
(defn fx [& args]
args)
<= (fx {:a 1} 2)
=> ({:a 1} 2)
But this removes the arity on my function. I want to have something like
(defn fx [{:keys [a]} b]
(MAGIC_FUNCTION_THAT_RETURNS_THE_ARGS_VALUES))
<= (fx {:a 1} 2)
=> ({:a 1} 2)
Is it possible to get a raw sequence of the values passed to a function?
By the time the function body is executed, the parameters have already been destructured. You could define your own defn macro and expose those values. I know Lighttable does this in their Instarepl to show the argument values.
Using argument destruction can help. The following works fine for me (as far as I know, it also works for old versions of clojure).
(defn example [ & [a b :as args]] [a b args])
(example 1 2)
=> [1 2 (1 2)]
The key point is that you can destruct the argument after &. The drawback is that it is possible to call the function with more arguments than expected (for example (example 1 2 3) is a valid invocation. Special care should be taken if this might be a problem.
Note: I came across this question while I was searching for similar feature. I kept digging and using an idea from here and :as as it was suggested in this answer, I found a solution for my problem.
I don't know of a way to do this as you describe, but depending on what you're wanting to do there are some options.
If you're wanting to ensure the function is only called with two arguments, consider a precondition:
(defn fx [& args]
{:pre [(= 2 (count args))]}
args)
user=> (fx 1 2)
(1 2)
user=> (fx 1 2 3)
AssertionError Assert failed: (= 2 (count args)) user/fx (NO_SOURCE_FILE:1)
If you're wanting to keep track of your intended arity of a function, but still have access to a vector of all args, you could add your own metadata:
(defn
^{:my.ns/arglists '([{:keys [a]} b])}
fx [& args]
args)
user=> (fx 1 2)
(1 2)
user=> (-> #'fx meta :my.ns/arglists first)
[{:keys [a]} b]
If you're just wanting access to the destructured values you described and access to an args value, you could use let:
(defn fx [{:keys [a]} b]
(let [args [{:a a} b]]
[a b args]))
user=> (fx {:a 1 :c 3} 2)
[1 2 [{:a 1} 2]]
user=> (fx {:a 1 :c 3} 2 4)
ArityException Wrong number of args (3) passed to: user$fx clojure.lang.AFn.throwArity (AFn.java:437)
You could also do a combination of these.
Not very nice as it requires to pass params as a vector, but seems apt
user.main=> (defn fx [[{:keys [a] :as e} b :as o]] [a b e o])
#'user.main/fx
user.main=> (fx [{:a 1} 2])
[1 2 {:a 1} [{:a 1} 2]]
user.main=>
You can use a macro to bind the arguments to symbol, _args in this example.
(defmacro defn-args [name args & body]
`(defn ~name ~args
(let [~'_args ~args]
~#body)))
You can then use _args in the body of the function to refer to the arguments:
user> (defn-args foo [{:keys [a b]} y z] _args)
user> (foo {:a 1 :b 10} 2 3)
[{:a 1, :b 10} 2 3]
This is the best I could cook up.
(def ^:dynamic *arguments* nil)
(defn unstructure [form]
(cond
(or (vector? form) (map? form)) (gensym)
(= form '&) '&
:else form))
(defmacro bind-args-defn [name args & body]
(let [simple-args (vec (map unstructure args))
i (.lastIndexOf simple-args '&)
[h r] (split-at (if (neg? i) (count simple-args) i) simple-args)
r (drop 1 r)]
`(defn ~name
~simple-args
(binding [*arguments* (lazy-cat ~#(map vector h) ~#r)]
(let [~args *arguments*]
~#body)))))
(bind-args-defn ;;my special val binding defn
silly ;;the name
[{:keys [a]} [b & c] & d] ;;the arg vector
{:vals *arguments* :a a :b b :c c :d d}) ;;the body
Obviously, this does not accept the full set of defn options (metadata, docstring, pre and post, arities, etc) that can be passed to defn, but I think it illustrates the idea.
It works by capturing the args vector, and then creating a simple-args vector of the same length as the original args but with no destructuring; using that as the defn argument vector. It then massages this simple-args vector into a sort of flat vector without &, which it assigns to *arguments*. *arguments* is then destructured using the original args vector. Kind of convoluted, but it does what I want at the moment.
> (silly {:a 1} [2 3 4] 5 6)
{:vals ({:a 1} [2 3 4] 5 6), :a 1, :b 2, :c (3 4), :d (5 6)}

How to append to variable from within another function in clojure?

The question doesn't really explain what I want to do but I couldn't think of anything else.
I have an empty map in the outer let function in a piece of code, and an integer array.
I want to iterate through the integer array, perform a simple task, and keep appending the resulting map to the variables in the outer variables.
(let [a {} ;outer variables
b {}]
(doseq [x [1 2 3]]
(let [r (merge a {x (* x x)}) ;I want to append this to a
s (merge b {x (+ x x)})] ;and this to b
(println (str "--a--" r "--b--" s)))))
But as soon as I get out of doseq, my a and b vars are still empty. I get that the scope of a and b doesn't extend outside of doseq for it to persist any changes done from within and that they are immutable.
How do I calculate the values of a and b in such cases, please? I tried to extract the functionality of doseq into another function and calling let with:
(let [a (do-that-function)])
etc but even then I couldn't figure out a way to keep track of all the modifications within doseq loop to then send back as a whole.
Am I approaching this in a wrong way?
Thanks
edit
Really, what I'm trying to do is this:
(let [a (doseq [x [1 2 3]] {x (* x x)})]
(println a))
but doseq returns nil so a is going to be nil :-s
All variables in clojure are immutable. If you need a mutable state you should use atoms or refs.
But in your case you can simply switch from doseq to for:
(let [a (for [x [1 2 3]] {x (* x x)})]
(println a))
Here is an example of solving your problem with atoms:
(let [a (atom {})
b (atom {})]
(doseq [x [1 2 3]]
(swap! a assoc x (* x x))
(swap! b assoc x (+ x x)))
(println "a:" #a)
(println "b:" #b))
But you should avoid using mutable state as far as possible:
(let [l [1 2 3]
a (zipmap l (map * l l))
b (zipmap l (map + l l))]
(println "a:" a)
(println "b:" b))
The trick is to think in terms of flows of data adding to existing data making new data, instead of changing past data. For your specific problem, where a data structure is being built, reduce is typically used:
(reduce (fn [result x] (assoc result x (* x x))) {} [1 2 3])
hehe, I just noticed that "reduce" might seem confusing given that it's building something, but the meaning is that a collection of things is "reduced" to one thing. In this case, we give reduce an empty map to begin with, which binds to result in the fn, and each successive mapping over the collection results in a new result, which we add to again with assoc.
You could also say:
(into {} (map (fn [x] [x (* x x)]) [1 2 3]))
In your question you wanted to make multiple things at once from a single collection. Here's one way to do that:
(reduce (fn [[a b] x] [(assoc a x (* x x)) (assoc b x (+ x x))]) [{} {}] [1 2 3])
Here we used destructuring syntax to refer to our two result structures - just make a picture of the data [with [vectors]]. Note that reduce is still only returning one thing - a vector in this case.
And, we could generalize that:
(defn xfn [n fs]
(reduce
(fn [results x] (map (fn [r f] (assoc r x (f x x))) results fs))
(repeat (count fs) {}) (range n)))
=> (xfn 4 [* + -])
({3 9, 2 4, 1 1, 0 0} {3 6, 2 4, 1 2, 0 0} {3 0, 2 0, 1 0, 0 0})
The result is a list of maps. And if you wanted to take intermediate steps in the building of these results, you could change reduce to reductions. Generally, map for transforming collections, reduce for building a single result from a collection.

Building a lazy, impure id generator

I'd like to know how to create an infinite, impure sequence of unique values in Clojure.
(def generator ...) ; def, not defn
(take 4 generator) ; => (1 2 3 4)
(take 4 generator) ; => (5 6 7 8). note the generator's impurity.
I think that such a design could be more convenient than e.g. wrapping a single integer value into a reference type and increment it from its consumers, as:
The proposed approach reduces the implementation details to a single point of change: the generator. Otherwise all the consumers would have to care about both the reference type (atom), and the concrete function that provides the next value (inc)
Sequences can take advantage many clojure.core functions. 'Manually' building a list of ids out of an atom would be a bit bulky: (take 4 (repeatedly #(swap! _ inc)))
I couldn't come up with a working implementation. Is it possible at all?
You can wrap a lazy sequence around an impure class (like a java.util.concurrent.atomic.AtomicLong) to create an id sequence:
(def id-counter (java.util.concurrent.atomic.AtomicLong.))
(defn id-gen []
(cons
(.getAndIncrement id-counter)
(lazy-seq
(id-gen))))
This works, but only if you don't save the head of the sequence. If you create a var that captures the head:
(def id-seq (id-gen))
Then call it repeatedly, it will return ids from the beginning of the sequence, because you've held onto the head of the sequence:
(take 3 id-seq)
;; => (0 1 2)
(take 3 id-seq)
;; => (0 1 2)
(take 3 id-seq)
;; => (0 1 2)
If you re-create the sequence though, you'll get fresh values because of the impurity:
(take 3 (id-gen))
;; (3 4 5)
(take 3 (id-gen))
;; (6 7 8)
(take 3 (id-gen))
;; (9 10 11)
I only recommend doing the following for educational purposes (not production code), but you can create your own instance of ISeq which implements the impurity more directly:
(def custom-seq
(reify clojure.lang.ISeq
(first [this] (.getAndIncrement id-counter))
(next [this] (.getAndIncrement id-counter))
(cons [this thing]
(cons thing this))
(more [this] (cons
(.getAndIncrement id-counter)
this))
(count [this] (throw (RuntimeException. "count: not supported")))
(empty [this] (throw (RuntimeException. "empty: not supported")))
(equiv [this obj] (throw (RuntimeException. "equiv: not supported")))
(seq [this] this)))
(take 3 custom-seq)
;; (12 13 14)
(take 3 custom-seq)
;; (15 16 17)
I had a fun time discovering something during answering your question. The first thing that occured to me was that perhaps, for whatever ultimate goal you need these IDs for, the gensym function might be helpful.
Then, I thought "well hey, that seems to increment some impure counter to generate new IDs" and "well hey, what's in the source code for that?" Which led me to this:
(. clojure.lang.RT (nextID))
Which seems to do what you need. Cool! If you want to use it the way you suggest, then I would probably make it a function:
(defn generate-id []
(. clojure.lang.RT (nextID)))
Then you can do:
user> (repeatedly 5 generate-id)
=> (372 373 374 375 376)
I haven't yet tested whether this will produce always unique values "globally"--I'm not sure about terminology, but I'm talking about when you might be using this generate-id function from within different threads, but want to still be sure that it's producing unique values.
this is another solution, maybe:
user=> (defn positive-numbers
([] (positive-numbers 1))
([n] (cons n (lazy-seq (positive-numbers (inc n))))))
#'user/positive-numbers
user=> (take 4 (positive-numbers))
(1 2 3 4)
user=> (take 4 (positive-numbers 5))
(5 6 7 8)
A way that would be more idiomatic, thread-safe, and invites no weirdness over head references would be to use a closure over one of clojures built in mutable references. Here is a quick sample I worked up since I was having the same issue. It simply closes over a ref.
(def id-generator (let [counter (ref 0)]
(fn [] (dosync (let [cur-val #counter]
(do (alter counter + 1)
cur-val))))))
Every time you call (id-generator) you will get the next number in the sequence.
Here's another quick way:
user> (defn make-generator [& [ii init]]
(let [a (atom (or ii 0 ))
f #(swap! a inc)]
#(repeatedly f)))
#'user/make-generator
user> (def g (make-generator))
#'user/g
user> (take 3 (g))
(1 2 3)
user> (take 3 (g))
(4 5 6)
user> (take 3 (g))
(7 8 9)
This is hack but it works and it is extremely simple
; there be dragons !
(defn id-gen [n] (repeatedly n (fn [] (hash #()))))
(id-gen 3) ; (2133991908 877609209 1060288067 442239263 274390974)
Basically clojure creates an 'anonymous' function but since clojure itselfs needs a name for that, it uses uniques impure ids to avoid collitions. If you hash a unique name then you should get a unique number.
Hope it helps
Creating identifiers from an arbitrary collection of seed identifiers:
(defonce ^:private counter (volatile! 0))
(defn- next-int []
(vswap! counter inc))
(defn- char-range
[a b]
(mapv char
(range (int a) (int b))))
(defn- unique-id-gen
"Generates a sequence of unique identifiers seeded with ids sequence"
[ids]
;; Laziness ftw:
(apply concat
(iterate (fn [xs]
(for [x xs
y ids]
(str x y)))
(map str ids))))
(def inf-ids-seq (unique-id-gen (concat (char-range \a \z)
(char-range \A \Z)
(char-range \0 \9)
[\_ \-])))
(defn- new-class
"Returns an unused new classname"
[]
(nth inf-ids-seq (next-int)))
(repeatedly 10 new-class)
Demonstration:
(take 16 (unique-id-gen [\a 8 \c]))
;; => ("a" "8" "c" "aa" "a8" "ac" "8a" "88" "8c" "ca" "c8" "cc" "aaa" "aa8" "aac" "a8a")

clojure unsequential let

it seem like clojure's let is sequential and would correspond to a scheme let* .
Does clojure have an unsequential binding mechanism like scheme's let?
I believe binding macro is parallel not sequential.
See: http://clojuredocs.org/clojure_core/clojure.core/binding
letfn is a parallel binding form for functions that exists to allow people to write mutually recursive local functions. It's not quite as general as you seek though it can be used in a pinch.
user> (letfn [(a [] 4)
(b [] c)
(c [] a)]
(a))
4
Binding can be used so long as you are assigning values to things in vars and want dynamic scoping
user> (def ^:dynamic x 4)
#'user/x
user> (defn foo [] x)
#'user/foo
user> (binding [x 8] (+ x (foo)))
16 ; the value of x that gets called by foo is modified by the caller
; yielding 16 instead of 12
user> (binding [x 8 a 7] (+ x (foo)))
; Evaluation aborted.
Unable to resolve var: a in this context
if you try to use parallel bindings the dynamic scoping will give different results than let* would in Scheme
user> (def ^:dynamic a 2)
#'user/a
user> (binding [x 8 a 7] (+ x a))
15
user> (binding [x 8 a (+ x 2)] (+ x a))
14 ; this would be 18 if the binding of x to 8 had been used
; instead the root value of 4 was used.
In general It is most common to bind sequentially or use nested lets if required.
binding doesn't give you the same capability as a parallel let because it depends on the existence of bindings. As mentioned letfn will work as long as you don't mind wrapping your values in functions. Another solution is to write a parallel let using a macro:
(defmacro letp
[bindings & exprs]
(let [bindings (partition 2 bindings)
vars (->> bindings (map first) vec)
values (->> bindings (map second))]
`((fn ~vars ~#exprs)
~#values)))
So the following holds:
(def a 7)
(letp [a 5 b a] b)
;;=> 7

Map restructuring

In clojure, I can destructure a map like this:
(let [{:keys [key1 key2]} {:key1 1 :key2 2}]
...)
which is similar to CoffeeScript's method:
{key1, key2} = {key1: 1, key2: 2}
CoffeeScript can also do this:
a = 1
b = 2
obj = {a, b} // just like writing {a: a, b: b}
Is there a shortcut like this in Clojure?
It's not provided, but can be implemented with a fairly simple macro:
(defmacro rmap [& ks]
`(let [keys# (quote ~ks)
keys# (map keyword keys#)
vals# (list ~#ks)]
(zipmap keys# vals#)))
user=> (def x 1)
#'user/x
user=> (def y 2)
#'user/y
user=> (def z 3)
#'user/z
user=> (rmap x y z)
{:z 3, :y 2, :x 1}
I wrote a simple macro for this in useful, which lets you write that as (keyed [a b]). Or you can parallel the :strs and :syms behavior of map destructuring with (keyed :strs [a b]), which expands to {"a" a, "b" b}.
The short answer is: no.
The main reason is that in Clojure, not only keywords but any value can be used as a key in a map. Also, commas are whitespace in Clojure. So {a, b} is the same as {a b} and will result in a map with one key-value pair, where the key is whatever a evaluates to.
You could however write a macro that takes a list of symbols and builds a map with the names of the symbols (converted to keywords) as keys and the evaluations of the symbols as values.
I don't think that is provided out of the box in clojure .. but hey this is lisp and we can use macros to have something like this:
(defmacro my-map [& s]
(let [e (flatten (map (fn [i] [(keyword (str i)) i]) s))]
`(apply hash-map [~#e]))
)
Usage:
(def a 10)
(def b 11)
(def result (my-map a b))
result would be your map