I am learning Clojure and was reading about doseq
when I noticed an example like below on the official Clojure doc for doseq
(doseq [x [-1 0 1]
y [1 2 3]]
(prn (* x y)))
My confusion is with the expression [x [-1 0 1] y [1 2 3]]
.
Does this signify a binding expression? I tried some amount of google search but could not come across any documentation that describes such a form.
Could someone help me with understanding the various syntax representations for binding forms in Clojure?
This is a "binding form" in that it "binds" the values from the expression to the name x
in turn. So it colloquially means an expression that binds names to values. This is part of "destructuring binding forms" which bind names to parts of a compound value such as a list or map.
The term "binding" instead of "setting" helps convey the difference between what this is doing and setting variables in some other programming languages. The name is attached to the value for the time it takes for the form inside the doseq
to run, then the name is released to be attached to another value.
Clojure offers arbitrary structural binding to give names to any part of a value in most places in the language that assign names (bind symbols)
(doseq [[x1 x2] [[-1 -1] [0 0] [1 1]]
y [1 2 3]]
(prn (* x1 x2 y)))
is also a binding expression though it looks slightly deeper into the data and assigns names to two values per item in the first vector (and assumes there are two numbers in each of them) I'm very fond of this tutorial on destructuring/binding
It is like a nested for loop in Java. You can also do the nesting "manually":
(dotest
(newline)
(println "version 1")
(doseq [x [1 2]
y [:a :b :c]]
(println x y))
(newline)
(println "version 2")
(doseq [x [1 2]]
(doseq [y [:a :b :c]]
(println x y))))
with results:
version 1
1 :a
1 :b
1 :c
2 :a
2 :b
2 :c
version 2
1 :a
1 :b
1 :c
2 :a
2 :b
2 :c
Note that doseq
always returns nil
, and is only good for generating side-effects (like printing to the screen).
A for
expression behaves similarly, but returns a (lazy) sequence of values (note we are generating a vector [x y]
on each loop):
(newline)
(println "For generates a (lazy) sequence:"
(for [x [1 2]
y [:a :b :c]]
[x y]))
with result:
For generates a (lazy) sequence: ([1 :a] [1 :b] [1 :c] [2 :a] [2 :b] [2 :c])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With