Clojure assoc applied to vector seems have inconsistent behaviour
When index is present in vector, assoc replace the value
(assoc [1 2 3 4 5] 3 42) => [1 2 3 42 5]
When index is next to last one, the vector grows (conj equivalent)
(assoc [1 2 3 4 5] 5 42) => [1 2 3 4 5 42])
Otherwise IndexOutOfBoundsExcpetion is thrown
though it useful in some cases like reduce assoc, this may lead to subtle bugs in a program
Is it expected behaviour or probably bug in assoc for vector?
It is expected. See the docstring for assoc, especially the last note regarding the index argument.
This is described at the top of p. 101 of Clojure Programming.
Related
This is 4clojure question #132. The problem statement is: "Write a function that takes a two-argument predicate, a value, and a collection; and returns a new collection where the value is inserted between every two items that satisfy the predicate.".
I came up with the following solution:
(fn [pred value coll]
(let [pairs (seq (zipmap coll (concat (rest coll) [0])))]
(mapcat #(if (apply pred %) [(first %) value] [(first %)]) pairs)))
The first unit test on the site fails, whereas it passes locally on my machine. I'll reproduce the test here:
(= '(1 :less 6 :less 7 4 3) (____ < :less [1 6 7 4 3]))
My question is, what am I doing wrong? Is there some restriction that the site puts on solutions that I'm not adhering to? Or some other issue?
4clojure uses clojure version 1.4, and you are likely using 1.8 or 1.9 alpha. There is a difference in the ordering of the result of zipmap, and this is the reason they are different.
;; 1.9 alpha 15:
(zipmap [1 2 3 4 5] [6 7 8 9 10])
=> {1 6, 2 7, 3 8, 4 9, 5 10}
;; 1.4:
(zipmap [1 2 3 4 5] [6 7 8 9 10])
=> {5 10, 4 9, 3 8, 2 7, 1 6}
Your solution happens to work on a more recent version of clojure, but you are relying on the ordering of a map when you use zipmap, and this is incorrect. The order of k-v pairs in a map is undefined, so your solution is only working by chance as you've currently implemented it.
Your solution will fail anyway if you're given an infinite sequence to process. Consider a different approach where you build the sequence as you walk it.
Good luck!
Just starting out with core.logic, version "0.8.11":
(q/run* [q]
(q/fresh [a]
(q/membero a [2 3]))
(q/membero q [1]))
I don't understand the result: (1 1).
My understanding is that I create another variable a with fresh, which can take a value of 2 or 3.
And q can take a value of 1. Therefore I was expecting to see something like: (1), or (1 2 1 3), or maybe ([1 2] [1 3]) or even ({:q 1 :a 2} {:q 1 :a 3}), but not the actual result.
Another example:
(q/run* [q]
(q/fresh [a]
(q/membero a [1 2 3])
(q/membero q [3 4 5])
(q/== a q)))
;; make sense to me, returns (3)
(q/run* [q]
(q/fresh [a]
(q/membero a [1 2 3]))
(q/membero q [3 4 5]))
;; does not make sense to me, returns (3 4 3 5 4 3 5 4 5)
;; I was expecting `(3 4 5)`
Could someone explain what is happening here?
core.logic can be viewed a search algorithm, searching for possible ways to assign values to all the relevant variables that don't cause a conflict. It has a lot of very smart pruning techniques so that it doesn't search subtrees that are known to be no good, but basically it is a search.
It found two ways to assign variables that satisfy your query:
a=2, q=1
a=3, q=1
So it is returning two results. But you only ask about q (that's what the argument to run* is, the set of variables you want to know the values of), and q is the same in both of those assignments, so you see the same result (1) twice. You should not in general assume that results from run* will be distinct, unless you have gone to some effort to make them so.
Likewise in your last example, there are three values you could assign to q, and each of them works for any of the three values you could assign to a, so you get 3*3=9 results, with each q value repeated three times. The order these results are returned in is (from your perspective) arbitrary; really they are ordered in a way that helps core.logic prevent getting deadlocked in other, more complicated programs. You could see all the a,q pairs if you wanted, by writing instead (q/run* [a q] ...).
I was looking at ways to reverse a collection using Clojure without using the reverse function and stumbled upon this solution.
(reduce conj '() [1 2 3 4 5]) => (5 4 3 2 1)
I have read the Clojure api with regard to how reduce works but am still baffled as to how it is working in this instance.
Also I have found if I were to pass a vector as the third argument instead of a list ie:
(reduce conj [] [1 2 3 4 5]) => [1 2 3 4 5]
I seem to get back the same vector.
I was wondering if anybody could give me a brief explanation as to to how reduce is working in both instances.
Also I have found this method also reverses a vector:
(into () [1 2 3 4]) => (4 3 2 1) ; ???
The doc string says: conj[oin]. Returns a new collection with the xs 'added'. (conj nil item) returns (item). The 'addition' may happen at different 'places' depending on the concrete type.
For a vector, the natural place to add is the end. For a list, the natural place to add is the front (as with 'cons').
Let's say I have a data structure like so:
[[1 2 3] [4 5 6] [[7 8 9] [10 11 12]]]
And what I want to end up with is:
[[1 2 3] [4 5 6] [7 8 9] [10 11 12]]
Is there any function that does this automatically?
Basically I'm converting/transforming a SQL result set to CSV, and there are some rows that will transform to 2 rows in the CSV. So my map function in the normal case returns a vector, but sometimes returns a vector of vectors. Clojure.data.csv needs a list of vectors only, so I need to flatten out the rows that got pivoted.
Mapcat is useful for mapping where each element can expand into 0 or more output elements, like this:
(mapcat #(if (vector? (first %)) % [%]) data)
Though I'm not sure if (vector? (first %)) is a sufficient test for your data.
A different approach using tree-seq:
(def a [[1 2 3] [4 5 6] [[7 8 9] [10 11 12]]])
(filter (comp not vector? first)
(tree-seq (comp vector? first) seq a))
I am stretching to use tree-seq here. Would someone with more experience care to comment on if there is a better way to return only the children other than using what is effectively a filter of (not branch?)
Clojure: Semi-Flattening a nested Sequence answers your question, but I don't want to mark this question as a duplicate of that one, since you're really asking a different question than he was; I wonder if it's possible to move his answer over here.
Is there a 'proper' way to iterate over a two-dimensional sequence in Clojure?
Suppose I had a list of lists of numbers, like this
((1 2 3)
(4 5 6)
(7 8 9))
and I wanted to generate a new list of lists with each number incremented by one. Is there an easy way to do this in Clojure without relying on nested maps or loop/recurs? I've been able to do it, but my solutions are ugly and I find them difficult to understand when I re-read them.
Thanks
What you describe is precisely what clojure.walk is for:
(def matrix [[1 2 3]
[4 5 6]
[7 8 9]])
(use 'clojure.walk :only [prewalk])
(prewalk #(if (number? %) (inc %) %) matrix)
=> [[2 3 4] [5 6 7] [8 9 10]]
Note 1: it is idiomatic to use vectors instead of parentheses for literal sequential collections.
Note 2: walk preserves type.
You can always just use a list comprehension. I find myself using them quite often coming from an imperative background so I don't know how idiomatic it is. In your specific case, you can do:
(for [my-list my-matrix] (map inc my-list))
For the two-dimensional case, you could do something like:
(map #(map inc %) my-two-d-list)
That's not too bad to read: apply the function #(map inc %) to each element in a list.
For the higher-order case, you're basically talking about tree-traversal. You'd want a function that takes in a tree and a function, and applies that function to each node in the tree. You can find functions for this in clojure.walk.
The other answers by Sean and Matt both show concise and effective ways of getting the right result.
However there are some important extensions you can make to this:
It would be nice to handle the case of higher dimensions
It is good to wrap the functionality in a higher order function
Example code:
;; general higher order function
(defn map-dimensions [n f coll]
(if (= n 1)
(map f coll)
(map #(map-dimensions (dec n) f %) coll)))
;; use partial application to specialise to 2 dimensions
(def map-2d (partial map-dimensions 2))
(map-2d inc
'((1 2 3)
(4 5 6)
(7 8 9)))
=> ((2 3 4) (5 6 7) (8 9 10))
Since the introduction of core.matrix in 2013, this is now a much better way of handling operations over multi-dimensional arrays:
(use 'clojure.core.matrix)
(def M [[1 2 3]
[4 5 6]
[7 8 9]])
(emap inc M)
=> [[2 3 4 ]
[5 6 7 ]
[8 9 10]]
Advantages of using core.matrix:
Clean, idiomatic Clojure code
Lots of general purpose n-dimensional array manipulation functions - transpose, shape, reshape, slice, subarray etc.
Ability to plug in high performance array implementations (e.g. for big numerical arrays)
A belated answer, and maybe not exactly what is needed: you could try flatten. It will return a seq that you can iterate over:
(flatten '((1 2 3)
(4 5 6)
(7 8 9)))
user=> (1 2 3 4 5 6 7 8 9)
And in order to increment matrix elements and reassemble the matrix:
(partition 3 (map inc (flatten '((1 2 3)
(4 5 6)
(7 8 9)))))