Clojure simple sort function error
I'm new in clojure, i try create functions thats will be sort collections and store it in object.
My code:
(defn uniq [ilist]
([] [])
(def sorted (sort ilist)))
I try to run it:
(uniq '(1,2,3,6,1,2,3))
but get开发者_Go百科 error:
#<CompilerException java.lang.IllegalArgumentException: Key must be integer (NO_SOURCE_FILE:0)>
What's wrong?
Thank you.
As with your other question, you're trying to use pattern-matching where it just doesn't apply. Your function would work fine1 if you deleted the ([] [])
entirely.
1 You also shouldn't use def
here; as the other respondents have noted, you want to use let
for establishing local bindings. However, here you don't need any bindings at all: just return the result of the sort
call. In fact, the def
will cause you to return a Var instead of the actual sorted list.
Since there's no need at all to use either 'let' or 'def', I have to agree with amalloy about Bart J's answer. Sure it warrants the upvotes because it's useful info, but it's not the right answer.
Actually, defining the function is kind of useless, since (sort ilist) would do the trick. The result of the function is the 'object' you want. That is, unless you want to use the result of the sort multiple times at different places in the function body. In that case, bind the result of sort to a function local variable.
If you only need the sort once, don't bother binding it at all, but just nest it inside other functions. For instance if you want to use it inside a unique function (which I guess is what you're wanting to do):
(defn uniq
"Get only unique values from a list"
[ilist]
; remove nils from list
(filter #(not(nil? %))
; the list of intermediate results from (reduce comppair sortedlist)
; (includes nils)
(reductions
; function to extract first and second from a list and compare
(fn comppair
[first second & rest]
(if (not= first second) second))
; the original sort list function
(sort ilist))))
(uniq '(1,2,3,6,1,2,3))
(1 2 3 6)
Then again, you could also just use the built-in distinct function, and take a look at it's source:
(distinct '(1,2,3,6,1,2,3))
(1 2 3 6)
(source distinct)
(defn distinct
"Returns a lazy sequence of the elements of coll with duplicates removed"
{:added "1.0"}
[coll]
(let [step (fn step [xs seen]
(lazy-seq
((fn [[f :as xs] seen]
(when-let [s (seq xs)]
(if (contains? seen f)
(recur (rest s) seen)
(cons f (step (rest s) (conj seen f))))))
xs seen)))]
(step coll #{})))
To store the sorted collection into a variable do this:
(let [sorted (sort your-collection)])
To understand the difference between a let and a def, this should help:
You can only use the lexical bindings made with let within the scope of let (the opening and closing parens). Let just creates a set of lexical bindings. def and let do pretty much the same thing. I use def for making a global binding and lets for binding something I want only in the scope of the let as it keeps things clean. They both have their uses.
精彩评论