This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-06-22
Channels
- # announcements (8)
- # architecture (1)
- # beginners (49)
- # calva (7)
- # cljdoc (7)
- # cljs-dev (4)
- # clojure (44)
- # clojure-italy (1)
- # clojure-spec (12)
- # clojurescript (88)
- # community-development (2)
- # cursive (8)
- # datomic (16)
- # fulcro (15)
- # immutant (3)
- # joker (10)
- # keechma (4)
- # lambdaisland (1)
- # luminus (7)
- # pathom (1)
- # qa (2)
- # re-frame (11)
- # reitit (8)
- # remote-jobs (1)
- # rewrite-clj (10)
- # shadow-cljs (1)
- # slack-help (2)
- # sql (1)
- # tools-deps (2)
- # vim (4)
- # xtdb (3)
Hi, I’ve been suffering from this stack overflow for a long time but couldn’t figure out why. What’s wrong with my code?
(defonce history-dict (atom '()))
(defonce message-dict (atom '()))
(defn add-completion-candidates!
([coll] (add-completion-candidates! coll message-dict))
([coll d]
(log/debug (prn-str coll))
(swap! d (comp seq #(take 5000 %) distinct #(apply conj %1 %2)) coll)))
(defn dict []
(seq (distinct (into @history-dict @message-dict))))
(defn completer []
(proxy [Completer] []
(complete [reader cli candidates]
(when-let [cs (not-empty (dict))]
(.addAll candidates
(seq (map #(Candidate. %)
cs)))))))
Sometimes, when I hit TAB, and this complete
is called, it gives stackoverflow.The error is not helping though.
#error {
:cause nil
:via
[{:type java.lang.StackOverflowError
:message nil
:at [clojure.lang.PersistentHashMap$BitmapIndexedNode index "PersistentHashMap.java" 681]}]
:trace
[[clojure.lang.PersistentHashMap$BitmapIndexedNode index "PersistentHashMap.java" 681]
[clojure.lang.PersistentHashMap$BitmapIndexedNode assoc "PersistentHashMap.java" 692]
[clojure.lang.PersistentHashMap assoc "PersistentHashMap.java" 143]
[clojure.lang.PersistentHashSet cons "PersistentHashSet.java" 99]
[clojure.lang.PersistentHashSet cons "PersistentHashSet.java" 17]
[clojure.lang.RT conj "RT.java" 677]
[clojure.core$conj__5390 invokeStatic "core.clj" 85]
[clojure.core$distinct$step__6413$fn__6414$fn__6416 invoke "core.clj" 5052]
[clojure.core$distinct$step__6413$fn__6414 invoke "core.clj" 5048]
[clojure.lang.LazySeq sval "LazySeq.java" 42]
[clojure.lang.LazySeq seq "LazySeq.java" 51]
[clojure.lang.RT seq "RT.java" 535]
[clojure.core$seq__5402 invokeStatic "core.clj" 137]
[clojure.core$take$fn__5909 invoke "core.clj" 2884]
[clojure.lang.LazySeq sval "LazySeq.java" 42]
[clojure.lang.LazySeq seq "LazySeq.java" 51]
[clojure.lang.RT seq "RT.java" 535]
[clojure.lang.RT nthFrom "RT.java" 981]
[clojure.lang.RT nth "RT.java" 940]
...
I thought it was because of thouse lazy-seq, so I use seq
everywhere to realize them, but am still getting the error.
seq
doesn’t realize the whole thing so you’re still getting lazy sequences built up.
Replace seq
with vec
in both functions to make it eager.
(although (vec (map ...))
can be just (mapv ...)
)
seq
only does enough work to distinguish an empty sequence from a non-empty sequence.
Also if I call those functions in repl, it works fine. It only throws error when in the app. Why is that?
And also, for future reference. Is it true that, whenever I realize a lazy-seq that’s very long, it will stack overflow?
The REPL forces evaluation of everything so it can print it.
Not all lazy seqs cause stack overflow on realization, regardless of size. It depends on how they are constructed.
In your case, you were essentially creating lazy sequences of nested lazy sequences so you hit a stack overflow fairly quickly there because of the nesting, not the length.
Does that help @markx?
Yeah that’s helpful! But could you point me to where the lazy seqs are being nested? As in which function?
@markx Every time add-completion-candidates!
runs it nests one lazy sequence inside another.
The value swapped into the atom is a lazy sequence that contains the previous lazy sequence.
OK I see. So every time I add more candidates, I need to realize the whole seq. Thanks man!
quick question, cuz i'm struggling a bit: if I use defrecord
and then implement a protocol function within it, can I wrap the record in an atom and then pass that atom into protocol's function? or do I have to deref before passing it in?
Pretty sure you would have to deref it. There are very few places in Clojure where things are deref'd for you.
cool, thanks
ah, that makes sense, thanks!
Like this:
(defprotocol Foo
(foo [this]))
(defrecord Bar [name]
Foo
(foo [this] (:name this)))
(extend-type clojure.lang.Atom
Foo
(foo [this] (foo @this)))
@deleted-user I am pretty sure I am remembering correctly that I have seen multiple times that some spec users prefer to create namespaces that have nothing but specs in them, and those namespace names are used as the namespace part of the spec name.
Normally what I do then, is I have a namespace of common specs ya. Like I'd create a: (s/def :labyrinth/pos-int (s/and int? pos?))
How do I specify a maven/clojars dependency on the command line with clojure
CLI? Is that possible w/o a deps.edn
file?
yes, use -Sdeps '{:deps {DEP {:mvn/version "VERSION"}}}'
As a rough estimate, how many working Clojure programmers worldwide do people think there are? I've always guessed around 10,000, but I'm not really sure if that's too high or low