This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-01-21
Channels
- # announcements (8)
- # babashka (12)
- # beginners (18)
- # biff (25)
- # calva (8)
- # clj-kondo (19)
- # clojure (53)
- # clojure-europe (3)
- # clojure-norway (3)
- # clojurescript (31)
- # emacs (9)
- # fulcro (12)
- # lsp (25)
- # membrane (1)
- # off-topic (58)
- # pathom (11)
- # pedestal (1)
- # proletarian (3)
- # re-frame (6)
- # releases (2)
- # shadow-cljs (7)
So in book “Programming Clojure” I really like the example of converting indexOfAny
into clojure. However I am not sure how can we more optimize the algorithm of it. For instance the Java code can be further optimized using HashSet for check and then it’ll pretty much return the first character it finds and not go through the whole array, so the number of iterations will be the index of first character found.
But in the clojure approach the method index-filter
will check all the elements. For small strings it should be fine, but I can see that it can be slow for very long strings. Is there a way we can optimize index-filter
to return a lazily evaluated list?
Ohh sure Optimized indexOfAny from Java:
public static int indexOfAny(String str, char[] searchChars) {
if (isEmpty(str) || searchChars == null || searchChars.length == 0) {
return -1;
}
Set<Character> searchSet = new HashSet<>();
for(char ch: searchChars)
searchSet.add(ch);
for(int i=0; i<str.length(); i++) {
char ch = str.charAt(i);
if(searchSet.contains(ch))
return i;
}
return -1;
}
index-of-any in clojure
(defn indexed [coll] (map-indexed vector coll))
(defn index-filter [pred coll]
(when pred
(for [[idx elt] (indexed coll) :when (pred elt)] idx)))
(defn index-of-any [pred coll]
(first (index-filter pred coll)))
index-filter
uses for
. and (doc for)
says that it
> yields a lazy sequence
So we don’t necessarily run through the whole string
ohh my bad, I didn’t realize that for does lazy evaluation. Thanks a lot for clarifying 🙂
You should write versions that use loop
and reduce
as an exercise. And those let you more strongly control the execution
Can anyone enlighten me what I'm missing with lazySeq, it seems like it doesn't want to compute 😞
(def common-hex (doall (->> (find-overlapping-colors xkcd-colors html-colors :hex)
(map (fn [c] (get-colordata-by-color (concat xkcd-colors html-colors) c)))
(map (fn [c] [:div {:style {:width 100
:height 100
:background-color (:hex (first c))}}])))))
;; => #'core-color-game/common-hex
(type common-hex)
;; => clojure.lang.LazySeq
(type (first common-hex))
;; => clojure.lang.PersistentVector
(type (doall common-hex))
;; => clojure.lang.LazySeq
doall
forces execution but doesn't change the type: it's still a LazySeq
-- it's just a fully-realized LazySeq
.
If you don't want it to be lazy, use mapv
instead of map
in the last expression (and then you won't need doall
) -- and you'll get a vector.
Thanks, I've should've read more closely. In my mind it should've been working just like calling .toList on an enumerable in c# or something
Or look at transducers which would give you:
(def common-hex (into []
(comp (map .. get-colordata-by-color ..)
(map .. [:div .. ] .. ))
(find-overlapping...)))
Hello, I'm trying to extend an interface, and to set a private field named "site". Can someone point me the correct way of doing this, I've tried to use a reify and with a proxy but with no success.
(proxy [PageProcessor] []
(set! (.this -site) Site/me)
(^Site getSite []
(.this site)))
...
the java equivalent is
public class GithubRepoPageProcessor implements PageProcessor {
private Site site = ();
...
Is there a particular reason, you’re trying to extend an interface? Do you really need to do this?