This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-06-28
Channels
- # announcements (9)
- # aws (2)
- # beginners (45)
- # biff (2)
- # calva (20)
- # cider (4)
- # cljdoc (15)
- # cljs-dev (9)
- # clojure (102)
- # clojure-austin (14)
- # clojure-europe (39)
- # clojure-france (3)
- # clojure-germany (1)
- # clojure-norway (39)
- # clojure-spec (1)
- # clojure-uk (3)
- # conjure (8)
- # cursive (6)
- # datahike (3)
- # datomic (8)
- # emacs (28)
- # events (1)
- # holy-lambda (6)
- # hyperfiddle (13)
- # jobs (11)
- # keechma (2)
- # lsp (4)
- # malli (33)
- # nbb (36)
- # off-topic (52)
- # pathom (5)
- # pedestal (2)
- # portal (1)
- # reagent (2)
- # reitit (3)
- # remote-jobs (1)
- # scittle (1)
- # spacemacs (2)
- # xtdb (5)
Hmm, lurer på om jeg ikke skal forsøke det gode gamle #clojure-europe trikset: God morgen!
Good morning!
Hva er målet egentlig? Ser ut som om #clojure-europe har lykkes i å få sin kanal til å hovedsakelig bestå av “good morning” 😁
For meg har det gitt en veldig hyggelig følelse av tilhørighet. Det er også et sted der jeg føler at jeg kan stille dumme/rare spørsmål blant venner som antar at slike spørsmål er stilt i beste hensikt.
Men, ja, som oftest er det bare masse good morning, men i blant blir det noe fint ut av det.
Jada, fint tiltak!
Innser at kommentaren min fremstår mer surmaget enn den var ment som
> Universal Greeting Time, an Internet Relay Chat convention whereby a person who joins a conversation is greeted "Good morning" and a person who leaves is bidden "Good night", regardless of the time zones of participants.
Ok, så her kommer et sånt spørsmål, eller noe. Gitt at vi er i et multithreaded miljø:
(defn sideffecting-expensive-operation [label]...)
(defn setup [some-atom label]
(let [r (sideffecting-expensive-operation label)]
(swap! some-atom assoc label r)))
Problemet med det over er at nå kan den tunge operasjonen bli kalt flere ganger for samme label
En løsning:
(defn setup [some-atom label]
(let [r (delay (sideffecting-expensive-operation label))]
(swap! some-atom (fn [m] (if (contains? m label) m (assoc m label (force r))))))
Men det gir jo også litt sånn vond smak i munnen.Grunnen til at vi ikke kan gjøre:
(defn setup [some-atom label]
(swap! some-atom (fn [m] (if (contains? m label) m (assoc m label (sideffecting-expensive-operation label))))))
er jo at funksjoner til swap!
kan bli kalt flere ganger og skal derfor ikke være sideffecting.Kan du memoize sideffecting-expensive-operation
? Det hindrer ikke at den kan bli kalt flere ganger samtidig hvis setup
kalles flere ganger samtidig, riktignok.
Hvis du vil garantere at sideffecting-expensive-operation
aldri kjører samtidig for samme verdi av label
kan du bruke locking
:https://clojuredocs.org/clojure.core/locking
Ein kan nytta fnil
...?
(defn setup [some-atom label]
(let [r (delay (sideffecting-expensive-operation label))]
(swap! some-atom update label (fnil force r))))
om eg liker den koden: tja, tja, tja...
Men ikkje så heilt verst, eller?Kva med locking
som msolli føreslo?
(defn setup [some-atom label]
(locking some-atom
(when (nil? (get @some-atom label))
(swap! some-atom assoc label (sideffecting-expensive-operation label)))
@some-atom))
Vakkert var det ikkjeThat's what I proposed. Cons is you now lock on the whole atom, limiting concurrency more than necessary. But it might well be acceptable...
Hvis du er bekymret for at den blir assoc'et på flere ganger, så kan du trygt gjøre
(swap! some-atom update label #(or % (delay (sideffecting-expensive-operation label))))
Dette var løsningen vi havnet på hos Norled, i hvert fall, etter en del diskusjoner her på Slack'en.
Er det viktig her om man bruker future
eller delay
?
Future betyr kanskje at man starter å regne ut svaret ved første kall til swap!
, uten å vente på første deref
?
hvis du vil starte prosessen med det samme, så er det bedre å gjøre noe slikt:
(-> (swap! some-atom update label #(or % (delay (sideffecting-expensive-operation label))))
(get label)
deref)