Understand Clojure binding syntax - clojure

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])

Related

How to merge maps and get a map of lists?

Let's say we a list of maps. Maps all have the same keywords, but we don't know the keywords beforehand.
[{:a 1 :b 2} {:a 3 :b 4}]
And what would be the idiomatic way of merging this list into such a map:
{:a [1 3]
:b [2 4]}
Doesn't seem hard, however as I start to implement the function, it gets super ugly and repetitive. I have a feeling that there are much cleaner ways of achieving this.
Thank you
You can actually get a pretty elegant solution by using several functions from the standard library:
(defn consolidate [& ms]
(apply merge-with conj (zipmap (mapcat keys ms) (repeat [])) ms))
Example:
(consolidate {:a 1 :b 2} {:a 3 :b 4})
;=> {:a [1 3], :b [2 4]}
One cool thing about this solution is that it works even if the maps have different key sets.
i would rather use double reduction to "merge" them with update:
(defn merge-maps-with-vec [maps]
(reduce (partial reduce-kv #(update %1 %2 (fnil conj []) %3))
{} maps))
user> (merge-maps-with-vec [{:a 1 :b 2} {:a 3 :b 4 :c 10}])
{:a [1 3], :b [2 4], :c [10]}
It is not as expressive as #Sam Estep's answer, but on the other hand it doesn't generate any intermediate sequences (like every-key-to-empty-vector map which also needs one extra pass through every entry of every map). Of course, premature optimizations are bad in general, but it won't hurt here i guess. Though the reduce based solution looks a bit more obscure, but being put into a library with proper docs it would not look as obscure to the end user (or to yourself a year after)
While many solutions are possible, here is one that uses some of the convenience functions in the Tupelo library:
(ns clj.core
(:use tupelo.core)
(:require [tupelo.schema :as ts]
[schema.core :as s] ))
(s/defn gather-keys
[list-of-maps :- [ts/KeyMap]]
(newline)
(let [keys-vec (keys (first list-of-maps))]
(s/validate [s/Keyword] keys-vec) ; verify it is a vector of keywords
(apply glue
(for [curr-key keys-vec]
{curr-key (forv [curr-map list-of-maps]
(get curr-map curr-key))} ))))
(deftest t-maps
(spyx
(gather-keys [{:a 1 :b 2}
{:a 3 :b 4} ] )))
(gather-keys [{:a 1, :b 2} {:a 3, :b 4}]) ;=> {:a [1 3], :b [2 4]}
Note that this solution assumes that each input map has an identical set of keys. Normally I'd want to enforce that assumption with a sanity check in the code as well.
Looking at the answer from Sam, I would rewrite it with some temporary variables to help document the sub-steps:
(defn consolidate-keys [list-of-maps]
(let [keys-set (set (mapcat keys list-of-maps))
base-result (zipmap keys-set (repeat [] )) ]
(apply merge-with conj base-result list-of-maps)))
(consolidate-keys [ {:a 1 :b 2}
{:a 3 :z 9} ] )
;=> {:z [9], :b [2], :a [1 3]}

Clojure: Why is flatten "the wrong thing to use"

I've read this kind of thing a couple of times since I've started Clojure.
For instance, here: How to convert map to a sequence?
And in some tweet I don't remember exactly that was more or less saying "if you're using flatten you're probably doing it wrong".
I would like to know, what is wrong with flatten?
I think this is what they were talking about in the answer you linked:
so> ((comp flatten seq) {:a [1 2] :b [3 4]})
(:b 3 4 :a 1 2)
so> (apply concat {:a [1 2] :b [3 4]})
(:b [3 4] :a [1 2])
Flatten will remove the structure from the keys and values, which is probably not what you want. There are use cases where you do want to remove the structure of nested sequences, and flatten was written for such cases. But for destructuring a map, you usually do want to keep the internal sequences as is.
Anything flatten can't flatten, it ought to return intact. At the top level, it doesn't.
(flatten 8)
()
(flatten {1 2, 3 4})
()
If you think you've supplied a sequence, but you haven't, you'll get the effect of supplying an empty sequence. This is the sort of leg-breaker that most core functions take care to preclude. For example, (str nil) => "".
flatten ought to work like this:
(defn flatten [x]
(if (sequential? x)
((fn flat [y] (if (sequential? y) (mapcat flat y) [y])) x)
x))
(flatten 8)
;8
(flatten [{1 2, 3 4}])
;({1 2, 3 4})
(flatten [1 [2 [[3]] 4]])
;(1 2 3 4)
You can find Steve Miner's faster lazy version of this here.
Probability of "probably"
Listen to people who say "you're probably doing it wrong", but also do not forget they say "probably", because it all depends on the problem.
For example if your task is to flatten the map where you could care less what was the key what was the value, you just need an unstructured sequence of all, then by all means, use flatten (or apply concat).
The reason it causes a "suspicion" is the fact that you had / were given a map to begin with, hence whoever gave it to you meant a "key value" paired structure, and if you flatten it, you lose that intention, as well as flexibility and clarity.
Keep in mind
In case you are still not sure what to do with a map for you particular problem, have a for comprehension in mind, since you would have a full control on what to do with the map as you iterate of it:
create a vector?
;; can also be (apply vector {:a 34 :b 42}), but just to use "for" for all consistently
user=> (into [] (for [[k v] {:a 34 :b 42}] [k v]))
[[:a 34] [:b 42]]
create another map?
user=> (into {} (for [[k v] {:a 34 :b 42}] [k (inc v)]))
{:a 35, :b 43}
create a set?
user=> (into #{} (for [[k v] {:a 34 :b 42}] [k v]))
#{[:a 34] [:b 42]}
reverse keys and values?
user=> (into {} (for [[k v] {:a 34 :b 42}] [v k]))
{34 :a, 42 :b}

How to iterate over ArrayMap in clojure?

I am totally new to clojure (started learning yesterday) and functional programming so please excuse my ignorance. I've been trying to read a lot of the clojure documentation, but much of it is totally over my head.
I'm trying to iterate over an ArrayMap of this set up:
{city1 ([[0 0] [0 1] [1 1] [1 0]]), city2 ([[3 3] [3 4] [4 4] [4 3]]), city3 ([[10 10] [10 11] [11 11] [11 10]])}
(^hopefully that syntax is correct, that is what it looks like my terminal is printing)
where the city name is mapped to a vector of vectors that define the points that make up that city's borders. I need to compare all of these points with an outside point in order to determine if the outside point is in one of these cities and if so which city it is in.
I'm using the Ray Casting Algorithm detailed here to determine if an outside point is within a vector of vectors.
Maps actually implement the clojure.lang.ISeq interface which means that you can use all the higher-level sequence operations on them. The single elements are pairs of the form [key value], so, to find the first element that matches a predicate in-city? you could e.g. use some:
(some
(fn [[city-name city-points]] ;; the current entry of the map
(when (in-city? the-other-point city-points) ;; check the borders
city-name)) ;; return the name of a matching city
cities)
You might also use keep to find all elements that match the predicate but I guess there is no overlap between cities in your example.
Update: Let's back off a little bit, since working with sequences is fun. I'm not gonna dive into all the sequence types and just use vectors ([1 2 3 ...]) for examples.
Okay, for a start, let's access our vector:
(first [1 2 3]) ;; => 1
(rest [1 2 3]) ;; => [2 3]
(last [1 2 3]) ;; => 3
(nth [1 2 3] 1) ;; => 2
The great thing about functional programming is, that functions are just values which you can pass to other functions. For example, you might want to apply a function (let's say "add 2 to a number") to each element in a sequence. This can be done via map:
(map
(fn [x]
(+ x 2))
[1 2 3])
;; => [3 4 5]
If you haven't seen it yet, there is a shorthand for function values where % is the first parameter, %2 is the second, and so on:
(map #(+ % 2) [1 2 3]) ;; => [3 4 5]
This is concise and useful and you'll probably see it a lot in the wild. Of course, if your function has a name or is stored in a var (e.g. by using defn) you can use it directly:
(map pos? [-1 0 1]) ;; => [false false true]
Using the predicate like this does not make a lot of sense since you lose the actual values that produce the boolean result. How about the following?
(filter pos? [-1 0 1]) ;; => [1]
(remove pos? [-1 0 1]) ;; => [-1 0]
This selects or discards the values matching your predicate. Here, you should be able to see the connection to your city-border example: You want to find all the cities in a map that include a given point p. But maps are not sequences, are they? Indeed they are:
(seq {:a 0 :b 1}) ;; => [[:a 0] [:b 1]]
Oh my, the possibilities!
(map first {:a 0 :b 1}) ;; => [:a :b]
(filter #(pos? (second %)) {:a 0 :b 1}) ;; => [[:b 1]]
filter retrieves all the matching cities (and their coordinates) but since you are only interested in the names - which are stored as the first element of every pair - you have to extract it from every element, similarly to the following (simpler) example:
(map first (filter #(pos? (second %)) {:a 0 :b 1}))
:: => [:b]
There actually is a function that combines map and filter. It's called keep and return every non-nil value its predicate produces. You can thus check the first element of every pair and then return the second:
(keep
(fn [pair]
(when (pos? (second pair))
(first pair)))
{:a 0 b 1})
;; => [:b]
Everytime you see yourself using a lot of firsts and seconds, maybe a few rests inbetween, you should think of destructuring. It helps you access parts of values in an easy way and I'll not go into detail here but it can be used with sequences quite intuitively:
(keep
(fn [[a b]] ;; instead of the name 'pair' we give the value's shape!
(when (pos? b)
a))
{:a 0 :b 1})
;; => [:b]
If you're only interested in the first result you can, of course, directly access it and write something like (first (keep ...)). But, since this is a pretty common use case, you get some offered to you by Clojure. It's like keep but will not look beyond the first match. Let's dive into your city example whose solution should begin to make sense by now:
(some
(fn [[city-name city-points]]
(when (in-city? p city-points)
city-name))
all-cities)
So, I hope this can be useful to you.

Why does Clojure's map destructuring look reversed?

Destructuring a map looks reversed to me. Can anybody explain what is happening?
I expect that this is the right form of destructuring a map
;=> (let [{:a a :b b} {:a 1 :b 2}] [a b])
which returns Exception Unsupported binding form: :a clojure.core/destructure/pb--4541 (core.clj:4029). Clojure documentations say that below is the right way. But it looks that keys and values are reversed.
This should be the right way:
;=> (let [{a :a b :b} {:a 1 :b 2}] [a b])
[1 2]
What is happening when destructuring a map?
It is not really reversed, actually it makes sense. It says: bind to symbol 'a' to value that is associated with the keyword :a
Are you aware of this when your map uses keywords as keys?
(let [{:keys [a b]} {:a 1 :b 2}] [a b])
Much neater and elegant!
Other variants exist if your keys are symbols or strings.
Also, it makes it possible to distinguish between these to cases:
cljs.user=> (let [{foo :foo :as bar} {:foo 3 :as 4}] [foo bar])
[3 {:foo 3, :as 4}]
cljs.user=> (let [{foo :foo bar :as} {:foo 3 :as 4}] [foo bar])
[3 4]

Difference between doseq and for in Clojure

What's the difference between doseq and for in Clojure? What are some examples of when you would choose to use one over the other?
The difference is that for builds a lazy sequence and returns it while doseq is for executing side-effects and returns nil.
user=> (for [x [1 2 3]] (+ x 5))
(6 7 8)
user=> (doseq [x [1 2 3]] (+ x 5))
nil
user=> (doseq [x [1 2 3]] (println x))
1
2
3
nil
If you want to build a new sequence based on other sequences, use for. If you want to do side-effects (printing, writing to a database, launching a nuclear warhead, etc) based on elements from some sequences, use doseq.
Note also that doseq is eager while for is lazy. The example missing in Rayne's answer is
(for [x [1 2 3]] (println x))
At the REPL, this will generally do what you want, but that's basically a coincidence: the REPL forces the lazy sequence produced by for, causing the printlns to happen. In a non-interactive environment, nothing will ever be printed. You can see this in action by comparing the results of
user> (def lazy (for [x [1 2 3]] (println 'lazy x)))
#'user/lazy
user> (def eager (doseq [x [1 2 3]] (println 'eager x)))
eager 1
eager 2
eager 3
#'user/eager
Because the def form returns the new var created, and not the value which is bound to it, there's nothing for the REPL to print, and lazy will refer to an unrealized lazy-seq: none of its elements have been computed at all. eager will refer to nil, and all of its printing will have been done.