I managed to redefine the built-in function vector by mistake.
More specifically, this is what I did:
(def vector [1 2 3 4 5 6])
And this is what I intended to do:
(def my-vector (vector 1 2 3 4 5 6))
Is there some way to "undo" that mistake, without restarting the REPL?
I.e., reverting vector back to its default definition.
(def vector #'clojure.core/vector)
Related
I'm trying to create a map from a list of 2-element Subvecs.
This works fine in Clojure:
(into {} (list (subvec [1 2 3] 1)))
>> {2 3}
But fails in ClojureScript, with the following error:
No protocol method IMapEntry.-key defined for type number: 2
Replacing (subvec [1 2 3] 1) with [2 3] makes it work in both languages.
I'm new to ClojureScript, and can't find where this behaviour is documented. Is this a bug? And how would you suggest going around it efficiently?
Thanks!
I think it's an omission. Subvectors should be indistinguishable from ordinary vectors, and therefore Subvec should have an implementation of IMapEntry added to it, like the one in PersistentVector.
I'm playing with a matrix implementation in Clojure which I'm doing for the fun of doing it and learning more about Clojure, rather than because I want to create the bestest fastest most coolest matrix implementation in the world.
One of the primary operations needed in code like this is the ability to return the value at a given row and column in a matrix, which of course I've written as a function
(mat-getrc m 2 3)
says "Give me the value at row 2, column 3 in matrix m". Perfectly good Clojure, but verbose and ugly. I'd rather write
(m 2 3)
but of course A) vectors (in my package matrices are just vectors) only respond to a single argument, and B) vectors don't know how to use the row and column number to figure out where the correct value is stored.
From looking at the docs for IFn (which vectors are supposed to implement) it appears that a two-argument version of invoke exists - but how do I get my "matrix" vectors to implement and respond to it?
Any suggestions and pointing-in-the-right-direction appreciated.
You can't modify how vectors are invoked as that's built into the implementation of vector, but you can define your own type that wraps a vector, acts as a vector, and is invokable however you like with deftype. You would need to extend many of the same interfaces that vectors implement (this is however a large list):
user=> (ancestors clojure.lang.PersistentVector)
#{clojure.lang.IEditableCollection clojure.lang.ILookup
java.util.concurrent.Callable java.lang.Runnable clojure.lang.IMeta
java.lang.Comparable clojure.lang.IReduceInit
clojure.lang.IPersistentCollection clojure.lang.IHashEq java.lang.Iterable
clojure.lang.IReduce java.util.List clojure.lang.AFn clojure.lang.Indexed
clojure.lang.Sequential clojure.lang.IPersistentStack java.io.Serializable
clojure.lang.Reversible clojure.lang.Counted java.util.Collection
java.util.RandomAccess java.lang.Object clojure.lang.Seqable
clojure.lang.Associative clojure.lang.APersistentVector
clojure.lang.IKVReduce clojure.lang.IPersistentVector clojure.lang.IObj
clojure.lang.IFn}
(def matrix [[1 2 3 4][5 6 7 8][9 10 11 12]])
As you say in your question this is possible:
(matrix 2)
But this is not:
(matrix 2 3)
This would be a standard way to get the index of an index:
(get-in matrix [2 3])
You can already nearly get what you want, just with a few more parens:
((matrix 2) 3)
You could define a higher order function:
(defn matrix-hof [matrix]
(fn [x y]
(get-in matrix [x y])))
Then put the function rather than the matrix in function position:
(let [m (matrix-hof matrix)]
(m 2 3))
I don't believe that exactly what you are asking is possible using either a function or a macro.
I am trying to really understand partial in Clojure. partial takes a function f and fewer than the normal arguments to f, and returns a fn that takes a variable number of additional args. When called, the returned function calls f with args + additional args. This is the working example for partial seems not making sense to me ((partial map *) [1 2 3] [4 5 6] [7 8 9]). map and * are functions; therefore partial is taking more than one function and invalidating the definition. Anyone can help me understand better?
There is nothing wrong with a function being an argument. In your case map * is created, which can be used later:
(def will-map-multiply (partial map *))
As with any partial function the rest of its arguments can be supplied later:
(will-map-multiply [1 2 3] [4 5 6] [7 8 9]) ;=> (28 80 162)
That was 'partialising' one of the arguments. It could have been two:
(def will-map-multiply-again (partial map * [1 2 3]))
(will-map-multiply-again [4 5 6] [7 8 9]) ;=> (28 80 162)
When using partial the first parameter must be a function, and the others can be whatever - no reason they can't also be functions.
Your example is a bit complex because multiplying requires two or more arguments, and hence map needs two or more sequences.
You're over-thinking it. The first argument to partial must be a function. The next arguments must be whatever would be valid arguments to that function you just named as the first argument -- including other functions, if your first parameter is a higher-order function like map or reduce or many others.
(partial map *)
The first argument is a function, map. The next argument is whatever would be a valid argument to map. Since map requires a function as its first argument, this partial expression requires a function as its second argument.
As simple as that. You can think of the * as an argument to the map first, and by extension, an argument to partial.
Functions are first-class values in Clojure. This means, you can pass them around like, for example, integers, maps or strings.
So, there’s nothing strange with (partial map *), where function * is just a map’s first argument. In your case, partial constructs a function which then passes additional collections to map. Let's see:
(partial map *)
;; becomes
(fn [coll1 coll2 coll3] ;; other arities ommited
(map * coll1 coll2 coll3))
;; let’s call this fn with your collections
((fn [coll1 coll2 coll3]
(map * coll1 coll2 coll3)) [1 2 3] [4 5 6] [7 8 9])
;; becomes
(map * coll1 coll2 coll3)
Again, the main point is that functions are first-class in Clojure and many other functional languages.
Hope this helps!
(partial map *) looks strange, but when one realizes that map takes a function as its first argument, it becomes more clear. * is just a function that takes variable number of arguments and multiplies them. Therefore,
(map * [1 2 3] [4 5 6] [7 8 9]) applies * to three triples of numbers and produces [28 80 162]. All this has nothing to do with partial. The confusion stems from the fact that in clojure functions are often passed as arguments to other functions (actually this is becoming common in all modern languages, even JavaScript!).
So, (partial map *) means exactly: take map with pre-selected first argument (*) and create a new function that uses its arguments as vectors to perform the mapping.
is there a single function for getting "from x to y" items in a sequence?
For example, given (range 10) I want [5 6 7 8] (take from 6th to nineth, or take 4 from the 6th,). Of course I can have this with a combination of a couple of functions (eg (take 4 (drop 5 (range 10)))), but is seems strange that there's not a built-in like pythons's mylist[5:9]. Thanks
subvec for vectors, primarily since it is O(1). For seqs you will need to use the O(n) of take/drop.
From a philosophical point of view, the reason there's no built-in operator is that you don't need a built-in operator to make it feel "natural" like you do in Python.
(defn splice [coll start stop]
(take (- stop start) (drop start coll)))
(splice coll 6 10)
Feels just like a language built-in, with exactly as much "new syntax" as any feature. In Python, the special [x:y] operator needs language-level support to make it feel as natural as the single-element accessor.
So rather than cluttering up the (already crowded) language core, Clojure simply leaves room for a user or library to implement this if you want it.
(range 5 9), or (vec (range 5 9)).
(Perhaps this syntax for range wasn't available mid-2012.)
I am trying to get the seq of all of the keys in a transient map:
(keys {3 4 5 6 7 8}) gives (3 5 7)
as I expect but:
(keys (transient {3 4 5 6 7 8}))
gives
#<CompilerException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.PersistentArrayMap$TransientArrayMap (NO_SOURCE_FILE:346)>
on the same note, how do I process using a transient map?
(map identity {3 4 5 6})
gives
([3 4] [5 6])
but
(map identity (transient {3 4 5 6}))
gives
#<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.PersistentArrayMap$TransientArrayMap>
This isn't really possible because of the interaction between laziness and mutability. (keys m) always returns a lazy sequence backed by the immutable m data structure, computing elements as necessary. But if m is a transient, it might change at any time, which would ruin the lazy key-sequence. You're really meant to not do anything too fancy with transients; and because it's so cheap to create transient or persistent versions of a data structure, it's not too onerous to go back and forth a few times if you really want to do something fancy.
I don't think there's a way to work on transients like you work on persistent structures. You need to create a persistent structure from your transients with persistence!
user> (map identity (persistent! (transient {3 4 5 6})))
([3 4] [5 6])
You can learn more about transients from Clojure docs.