This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-10-31
Channels
- # ai (5)
- # announcements (11)
- # beginners (19)
- # biff (1)
- # calva (8)
- # cider (3)
- # clj-kondo (12)
- # clojure (97)
- # clojure-europe (39)
- # clojure-nl (1)
- # clojure-norway (74)
- # clojure-uk (35)
- # clojurescript (8)
- # component (8)
- # conjure (4)
- # cursive (13)
- # data-science (1)
- # datahike (55)
- # datomic (2)
- # emacs (3)
- # etaoin (6)
- # gratitude (1)
- # hoplon (12)
- # hyperfiddle (54)
- # introduce-yourself (1)
- # lsp (70)
- # missionary (40)
- # music (1)
- # off-topic (79)
- # re-frame (78)
- # releases (4)
- # sql (5)
- # squint (9)
- # tree-sitter (4)
- # xtdb (20)
Leo’s next talk - Tues 10/31. about situated programs, what is the central problem, and how missionary solved it
I’m looking for a general way to fake a causal relationship between sibling graph nodes. Here’s my attempt:
(defmacro cause
"Fake a sequential causal relationship over `forms`."
[& forms]
(let [[form & forms] forms]
(if (seq forms)
`(case ~form
(cause ~@forms))
form)))
Is this alright?1- Don't macro this, we do not promise to keep this working. Write it out each time 2- we want to understand what circumstance you're encountering that makes you reach for this, so we can solve it in a better way
Search "causal" for past discussions
Basically just flipping some CSS classes.
(cause
(reset! processing-atom true)
(transact-some-stuff-to-server …)
(reset! processing-atom false))
Does this idiom solve your problem https://electric.hyperfiddle.net/user.demo-chat!%43hat
(catch Pending e (dom/style {:background-color "yellow"}))
The stuff I need to control sits in an awkward place, which is why I’m proxying status to an atom. Will true
in the try
and false
in a finally
do the trick?
i'm not sure that finally
makes sense in electric
you can e/on-unmount
in the catch body
This does not work:
(try
(reset! processing-atom true)
(when-let [atom-ident (e/server (e/offload #(create-new-atom node current-space prototype account)))]
(router/route-to-entity! atom-ident))
(catch Pending _
(e/on-unmount #(reset! processing-atom false))))
first, put the reset! inside the pending body
i dont know why it doesn't work though
(let [load-state (try (e/server ...) ::done (catch Pending _ ::pending))] ...)
is maybe a useful idiom
More context:
(dom/on "click"
(e/fn [_evt]
(try
(when-let [atom-ident (e/server (e/offload #(create-new-atom node current-space prototype account)))]
(router/route-to-entity! atom-ident))
(catch Pending _
(reset! processing-atom true)
(e/on-unmount #(reset! processing-atom false))))))
This sets the atom to false
initially, but does nothing else, it seems.
(e/fn [_evt]
(reset! processing-atom
(try (e/server (e/offload #(create-new-atom node current-space prototype account)))
false
(catch Pending _ true))))
try outside of dom/on (we don’t like dom/on it is dying after differential electric lands)
This works:
(case (helpers/on! "click")
(reset! processing-atom
(try (e/server (e/offload #(create-new-atom node current-space prototype account)))
false
(catch Pending _ true))))
Where helpers/on!
is:
(defmacro on!
([type]
`(nil->pending (dom/on! ~type identity)))
([type f]
`(nil->pending (dom/on! ~type ~f))))
It doesn’t work twice though, after it’s run the first time, it dies.
If I don’t init with pending
, it’ll run on app boot.what is "dies"
what is "nil->pending"
i dont understand why you would artifically throw pending here
and (Failure. (Pending.)) is i think not what you want it to be. You need to throw
Right, I’m reaching the limits of my understanding here. The goal is just to prevent triggering the else
case of case
on boot, after putting the work outside of on!
.
(when click-event ...) ?
Like the one above, this works, but only once. The true
branch of when
won’t execute again for another truthy value, I presume.
(when (dom/on! "click" identity)
(reset! processing-atom
(try (e/server (e/offload #(create-new-atom node current-space prototype account)))
false
(catch Pending _ true))))
dom/on manages the pending, if you catch it and don't rethrow it'll do weird stuff. I think you want
dom/on click
reset! atom true
e/server ...
e/on-unmount reset! atom false
Nice, I’ll skip the case
stuff then. I’m a little bit disappointed that I couldn’t get the “inverted” layout to work. But I’ve been there and failed previously as well.
there's a special calva command happening here right?
run it line by line (tap becomes println), or run the whole test
i'm not sure what you're seeing, i will try to find out
running partial tests with the special calva command is going to leak processes, you must cancel each process
Dustin, this calva command to eval, once you get used to it, you start using it so often, it’s so productive. Worth getting used to it. Here are the variants.
@U0ETXRFEW i can't repro the 45350
I used eval from start of toplevel form to cursor
I can’t reproduce it either. But I had been doing eval to cursor a lot of times before that, so maybe that is how to repro. (If the repro is any interesting, and simply not just a non supported use.)
We made a missionary quickstart, please try it and give feedback!
Connection details for the missionary talk starting shortly: https://www.youtube.com/watch?v=ZcsTWFTmUO0
That link no longer works but this one does: https://www.youtube.com/watch?v=xtTCdT6e9-0
I added the ability for users to "upvote tags" that correspond to hyperlinks on http://NextApex.co but I still need to learn the tricks of the trade for catching the "upvote click" and not vacillating on it. There is some vacillation/wigglyness that occurs, I reckon due to the streaming nature of the differential. @dustingetz you mentioned there were some tricks, I will post the component code here although if you need more feel free to tell me
(e/defn TagItem [id]
(e/server
(let [e (xt/entity db id)
xt-id (:xt/id e)
author (:tag/minted-by e)
tag-id (:tag/id e)
tag-minted-at (:tag/minted-at e)
title (:tag/title e)
target-id (:tag/target e)
upvotes-set (:tag/upvotes-set e)
upvotes (:tag/upvotes e)
downvotes-set (:tag/downvotes-set e)
downvotes (:tag/downvotes e)
u (if (not= "" online-user) online-user nil)
vw true]
(e/client
(dom/div (dom/props {:class "fr"})
(dom/div (dom/props {:class "fc"}))
(dom/div (dom/props {:class ["fc" "atag"]})
(dom/div (dom/props {:class "upvote-tag"})
(if (not (nil? u))
(ui/button
(e/fn []
(e/server
(e/offload
#(xt/submit-tx !xtdb
[[:xtdb.api/put
(if (and u (contains? upvotes-set u) vw) ;;vw is verified login
;; user has upvoted, remove their upvote
(-> e
(update :tag/upvotes-set disj u)
(update :tag/upvotes dec))
;; user hasn't upvoted, include their upvote
(-> e
(update :tag/upvotes-set conj u)
(update :tag/upvotes inc)))]]))))
(dom/props {:class (if (contains? upvotes-set u) "alreadyupvoted" "notyetupvoted")})
(dom/text "▲ " (count upvotes-set)))
(dom/div (dom/text "▲ " (count upvotes-set)))))
(dom/div
(dom/props {:class ""})
(dom/text title)))
(when (= "R" online-user)
(dom/div (dom/props {:class "fc"})
(ui/button
(e/fn []
(e/server
(let [target-entity (xt/entity db target-id)
updated-target (update target-entity :item/tags disj title)]
(e/discard
(xt/submit-tx !xtdb [[:xtdb.api/put updated-target]
[:xtdb.api/delete xt-id]])))))
(dom/props {:class "delete"})
(dom/text "✗")))))))))
#?(:clj
(defn tags-for-newsitem [db newsitem-id]
(->> (xt/q db '{:find [(pull ?t [:xt/id :tag/minted-by :tag/id :tag/minted-at :tag/title :tag/upvotes-set :tag/upvotes])]
:where [[?t :tag/target nws-id]]
:in [nws-id]} newsitem-id)
(map first)
(sort-by :tag/upvotes >)
vec)))
The (sort-by :tag/upvotes >)
sometimes makes the tags jump around to stay sorted. this makes the "vacillation" very apparent.