Persisting metadata over a map in Clojure - clojure

I was wondering the best way to accomplish this:
Pass along metadata important for the pipeline, but not actually part of the value
Here's what I have:
; Attach the metadata
^{:doc "How obj works!"} [1 2 3]
; [1 2 3]
; ensure that it's attached
(meta ^{:doc "How obj works!"} [1 2 3])
; {:doc "How obj works!"}
; map over the values
(map inc ^{:doc "How obj works!"} [1 2 3])
; [2 3 4]
; try and get the metadata after the map
(meta (map inc ^{:doc "How obj works!"} [1 2 3]))
; nil
I'm pretty sure I know why this is happening, but I'd like to know if there's a good way to do this, or if there's a better way to approach this problem.

Regarding a better way, there probably is. If I had an object substantial enough to require a metadata docstring explaining how it works, I think I would define records or types, and maybe a protocol.
Without knowing what you're doing or why, however, I have no informed opinion on the matter.
If you are certain you want to map a function and preserve metadata, you could try something along the outline of the following:
(defn meta-preserving-map
[f & cs]
(let [data (apply merge (map meta cs))]
(with-meta (apply map f cs) data)))

Related

How can i loop through a Collection in Clojure?

I have a Matrix and i want to print the rows of it.
I tried to implement it like this but i dont know how to loop and get the other elements!
(defn p! [args]
(println (first args))
(drop args))
(p! [[1 2] [3 4]]) --> [1 2]
the output should look like this
;; 12
;; 34
I would suggest using the core.matrix facilities for this task. It has a mature and time-tested API. Among other things, it provides you with a pm function that pretty-prints a matrix and accepts a custom element formatter as a parameter.
You might find its implementation interesting, since it can give you an idea of printing array-like structures. (TL;DR: It approaches it with a recursive algorithm that employs a dotimes fn quite heavily.)
With this library you might end up implementing your p! fn like this:
(require '[clojure.core.matrix :as mx])
(defn p! [args]
(mx/pm (mx/matrix args)))
(p! [[1 2] [3 4]])
[[1 2]
[3 4]]
=> nil
If you would like to keep things simple and/or omit the brackets, then the easiest implementation would be along these lines:
(defn p! [args]
(doseq [row args]
(println (clojure.string/join " " row))))
(p! [[1 2] [3 4]])
1 2
3 4
=> nil
Cheers!

Can I transduce / educe over multiple collections without concatting them

Below is a bare-bones version of what I'm doing:
(eduction (map inc) (concat [1 2] [3 4]))
; -> (2 3 4 5)
Is there a way to get the same eduction, without having to pay the cost of concat, which creates an intermediate lazy seq?
The following would perhaps already be a bit less wasty, as instead of the lazy seq, we just have a vector, but I wonder if even that can be avoided.
(eduction (comp cat (map inc)) [[1 2] [3 4]])
It may be simplest to process your collections separately and combine the results. There is, in fact, an easy reducers-based solution that does exactly that under the covers.
The clojure.core.reducers namespace has cat, a combining function for fold, that you can repurpose to construct a reducible concatenation of your vectors.
(require '[clojure.core.reducers :as r])
(eduction (map inc) (r/cat [1 2] [3 4]))
;; => (2 3 4 5)
This avoids the lazy sequence used in concat. If you have more than two vectors, you can concatenate them all with (reduce r/cat [] colls) or similar.
This approach did speed up some of the experiments I did, though not your particular example.
You can also do this without the reducer just using the built in cat transducer
(eduction (comp cat (map inc)) [[1 2] [3 4]])
;; => (2 3 4 5)

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.

How do I modify a portion of a vector in Clojure?

I am wondering if I'm missing something basic involving vector manipulation. Let's say I have the following:
(def xs [9 10 11 12 13])
(def idx [0 2])
(def values [1 3])
If I want to return the vector [1 10 3 12 13] in Matlab, I would write xs(idx) = values.
In Clojure, is there a primitive way of achieving this? Right now I'm using the following function:
(defn xinto [seq idx val]
(apply assoc seq (interleave idx val)))
Thanks.
It's a bit awkward because you've split up idx and values into two seqs, when they're conceptually a map of indexes to values. So if you'll permit me a little creative modification of your data format:
(def x [9 10 11 12 13])
(def changes {0 1, 2 3})
(defn xinto [v changes]
(reduce (fn [acc [k v]]
(assoc acc k v))
v
changes))
(xinto x changes) ;; gets the result you want
If you generate idx and values in some weird way that it's not convenient to group them together, you can group them later with (map list idx values) and then use my xinto implementation with that.
I'd probably use reduce for this:
(reduce
(fn [old [i v]] (assoc old i v))
x
(map vector idx values))
However, if you really want to do this a lot (Matlab-style) then I'd suggest creating some helper macros / functions to create some kind of DSL for vector manipulation.
Could not find something better.
In the core sequence functions there is replace, but it works on values, not on keys.
So,
(replace {9 2} x)
Would return
[2 10 11 12 13]
If you plan to do math related things in Clojure, I also propose you have a look at Incanter. It has a lot of APIs to manipulate mathematical data.

How can I add meta-data to a closure vector?

I wish to add type data to a clojure vector by adding meta data. What do I need to add to this to achieve this:
(def r (ref [1 2 3]))
Note that I want to add the meta data to [1 2 3]. Is this even the right way of doing this? I mean, should I be adding meta-data to the vector [1 2 3] to "r"?
I think it should be added to 'r':
user=> (def r (ref [1 2 3] :meta {:type "vector"}))
#'user/r
user=> (meta r)
{:type "vector"}