简体   繁体   中英

Clojure: Vector is not immutable

I'm running into a problem where immutability suddenly doesn't hold for my vectors. I was wondering if there was a way to create fresh, immutable vector copies of a given set.

Clojuredocs suggested "aclone" but that is giving me an error stating that there's no such method.

(defn stripSame [word wordList]
  (def setVec (into #{} wordList))
  (def wordSet word)
  (def wordVec (into #{} [wordSet]))
  (def diffSet (set/difference setVec wordVec))
  (def diffVec (into [] diffSet))
  diffVec) 


(defn findInsOuts [word passList]
  (def wordList (stripSame word passList))
  (println word wordList)
  (def endLetter (subs word (dec (count word))))
  (def startLetter  (subs word 0 1))
  (println startLetter endLetter)
  (def outs (filter (partial starts endLetter) wordList))
  (def ins (filter (partial ends startLetter) wordList))
  ;(println ins outs)
  (def indexes [ (count ins) (count outs)])
  indexes)

(defn findAll [passList]
  (def wordList   (into [] passList) ))
  (println wordList)
  (loop [n 0 indexList []]
    (println  "In here" (get wordList n) wordList)
    (if (< n (count wordList))
      (do
        (def testList wordList)
        (def indexes (findInsOuts (get wordList n) testList))
        (println (get wordList n) indexes)
        (recur (inc n) (conj indexList [(get wordList n) indexes]))))))

passList is a list of words like so (lol at good) which is then cast into a vector.

So basically findAll calls findInsOuts which goes through every word in the list and sees how many other words start with its last letter but which first removes the search word from the vector before performing some function to prevent duplicates. The problem is that somehow this vector is actually mutable, so the copy of the vector in findAll also has that value permanently stripped.

When I try to create a new vector and then act on that vector the same thing still happens, which implies that they're aliased/sharing the same memory location.

How can I create a fresh vector for use that is actually immutable?

Any help is appreciated

I'm afraid your code is riddled with misunderstandings. For a start, don't use def within defn . Use let instead. This turns your first function into ...

(defn stripSame [word wordList]
  (let [setVec (into #{} wordList)
        wordSet word
        wordVec (into #{} [wordSet])
        diffSet (clojure.set/difference setVec wordVec)
        diffVec (into [] diffSet)]
    diffVec))

For example,

=> (stripSame 2 [1 2 :buckle-my-shoe])
[1 :buckle-my-shoe]

The function can be simplified to ...

(defn stripSame [word wordList]
  (vec (disj (set wordList) word)))

... or, using a threading macro, to ...

(defn stripSame [word wordList]
  (-> wordList set (disj word) vec))

I don't think the function does what you think it does, because it doesn't always preserve the order of elements in the vector.


If I were you, I'd work my way through some of the community tutorials on this page . There are several good books referred to there too. Once you get to grips with the idioms of the language, you'll find the sort of thing you are trying to do here much clearer and easier.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM