This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-06-29
Channels
- # announcements (6)
- # beginners (110)
- # calva (18)
- # clj-kondo (19)
- # cljs-dev (27)
- # clojars (10)
- # clojure (38)
- # clojure-art (2)
- # clojure-europe (13)
- # clojure-germany (1)
- # clojure-norway (26)
- # clojure-uk (2)
- # clojurescript (10)
- # conjure (9)
- # cursive (12)
- # data-science (3)
- # datomic (22)
- # emacs (8)
- # helix (9)
- # honeysql (18)
- # introduce-yourself (1)
- # jobs (1)
- # leiningen (8)
- # lsp (22)
- # missionary (9)
- # nbb (11)
- # off-topic (83)
- # pathom (5)
- # pedestal (4)
- # polylith (1)
- # portal (1)
- # re-frame (3)
- # reitit (15)
- # remote-jobs (1)
- # rum (4)
- # shadow-cljs (88)
- # specter (12)
- # testing (1)
- # vim (39)
God morgon 🙂
Følger opp gårsdagens kollokvie med en alternativ løsning på @slipsets problem:
(defn sideffecting-expensive-operation
[label]
(let [x (rand-int 2000)]
(println "Computing" label)
(Thread/sleep 2000)
(println "Done computing" label)
x))
(defn setup
[some-atom label]
(let [r (locking label
(sideffecting-expensive-operation label))]
(swap! some-atom assoc label r)))
(def a (atom {}))
(do
(future (setup a "foo"))
(future (setup a "foo"))
(future (setup a "bar")))
Denne vil kjøre sideffecting-expensive-operation flere ganger for samme label. Men hvis vi memoizer den blir det bra:
(def sideffecting-expensive-operation-memo (memoize sideffecting-expensive-operation))
(defn setup
[some-atom label]
(let [r (locking label
(sideffecting-expensive-operation-memo label))]
(swap! some-atom assoc label r)))
gir (locking label
mening når label er string/keyword som ikke nødvendigvis er samme instance selv om det er samme verdi når vi kaller funksjonen?? Jeg tror locking er bare meningsfylt når du har samme ting (dvs identical, samme plass i minne) du prøver å låse fra froskjelige tråder
Uten memo:
Computing foo
Computing bar
Done computing bar
Done computing foo
Computing foo
Done computing foo
Med memo:
Computing foo
Computing bar
Done computing foo
Done computing bar
gir (locking label
mening når label er string/keyword som ikke nødvendigvis er samme instance selv om det er samme verdi når vi kaller funksjonen?? Jeg tror locking er bare meningsfylt når du har samme ting (dvs identical, samme plass i minne) du prøver å låse fra froskjelige tråder
Literals vil være identical men ikke f.eks
(identical? "foo" (str "f" "oo"))
=> false
Ah, det forandrer saken! Da funker ikke løsningen min: :thinking_face:
(let [foo-1 "foo"
foo-2 (str "f" "oo")]
(future (setup a foo-1))
(future (setup a foo-2))
(future (setup a "bar")))
Computing foo
Computing bar
Computing foo
Done computing foo
Done computing foo
Done computing bar
Det er mulig å fikse da om det skulle bli nødvendig en dag, men bare for String:
(identical? "foo" (.intern (str "f" "oo")))
=> true
label
høres ut som String. 🙂 Men hvis det er et keyword vil problemet allerede være løst, siden de er intern
-ert (?) automatisk.
Da funker det igjen:
(let [foo-1 "foo"
foo-2 (str "f" "oo")]
(future (setup a foo-1))
(future (setup a foo-2))
(future (setup a "bar")))
Computing foo
Computing bar
Done computing foo
Done computing bar
Computing foo
Done computing foo
(Uten memoize)Relatert: https://clojuredocs.org/clojure.core/compare-and-set! frå notatane:
The note that compare-and-set! uses equality comparison is wrong, compare-and-set! really does use identity comparison (Java ==). Internally, Clojure uses the AtomicReference.compareAndSet(old, new) method.
The reason his example works is due to interning of the a symbol: in his example, each a is the same (identical) object.
But as you can see from the example below, even numeric autoboxing can lead to surprising results:
(def a (atom 0))
;=> #'user/a
(compare-and-set! a 0 100)
;=> true
;(compare-and-set! a 100 200)
;=> true
;; Fails?! (on Oracle JVM 8 with default settings)
(compare-and-set! a 200 300)
;=> false
@a
;=> 200 ; WAT?
Clojure almost always uses boxed numbers (via Java autoboxing) unless you take special steps to avoid it. compare-and-set! only accepts Objects, so numbers are autoboxed to Longs.
Java JVMs will usually intern small integers; by default Oracle/OpenJDK will intern -127 to 128 (the byte range) so that all such boxed numbers are identical. This can be altered with the -XX:AutoBoxCacheMax= command line flag. This may vary by JVM implementation, too.
This is due to the impl of Long/valueOf
which caches some smaller values: (I guess)
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}