hyperfiddle

tobias 2025-03-13T07:30:33.408619Z

In case it's useful to anyone, a here's a little utility macro to force expressions to run in order by turning them into nested case expressions. It's just syntax sugar. See thread https://clojurians.slack.com/archives/C7Q9GSHFV/p1741009371615649 for an example of where this kind of thing might be handy. I'm a newb at writing macros but this seems to work ๐Ÿคž

(defmacro do-in-order
  "Transforms (do-in-order a b c ...) into nested case expressions like (case a (case b (case c ...)))."
  [& exprs]
  (if (empty? exprs)
    nil
    (reduce (fn [inner# expr#]
              `(case ~expr# ~inner#))
      (last exprs)
      (reverse (butlast exprs)))))

oฮปv 2025-03-13T09:20:44.285909Z

Very nice! If I may suggest a minor diff for the docstring: (case a (case b c ...)) -> (case a (case b (case c ...)))

tobias 2025-03-13T09:47:36.635069Z

Good idea, thanks! Have updated. Also added #'s to make inner# and expr# gensyms.

oฮปv 2025-03-13T09:51:22.302629Z

That isn't necessary is it?

tobias 2025-03-13T10:17:48.049099Z

I think you're right it's not necessary as they're only used in the anonymous function. I'm still getting the hang of macro writing ๐Ÿ˜

๐Ÿ‘ 1
2025-03-13T10:21:45.104489Z

I have one of these too ๐Ÿ™‚

(defmacro sequentially
  "Run each of `exprs` in sequence."
  {:style/indent 0}
  [& exprs]
  ;; Use `case` to enforce sequence. See for example
  ;; 
  (when exprs
    (let [[e & es] exprs]
      (if es
        `(case ~e (sequentially ~@es))
        e))))

๐Ÿคฉ 2
tobias 2025-03-13T11:04:38.097609Z

I tried writing mine with recursion at first too I couldnโ€™t get it to work. I will study your version to learn from it

tobias 2025-03-13T12:05:09.103149Z

TIL ~@ unquote splicing ๐Ÿ˜

๐Ÿ†’ 1
oฮปv 2025-03-13T12:20:35.122179Z

Thereโ€™s also #?@ splicing reader conditional which I learned about recently :^) https://clojure.org/guides/weird_characters#_splicing_reader_conditional

xificurC 2025-03-13T12:25:20.048619Z

reduce can auto-consume the first arg (or throw), leaving you with

(reduce #(list 'case %2 %) (reverse '(a b c)))

Dustin Getz (Hyperfiddle) 2025-03-13T12:40:43.324319Z

@xifi should we add this to electric-contrib? If users feel like they need to write this, at least we can control the implementation

Dustin Getz (Hyperfiddle) 2025-03-13T12:44:14.489429Z

All, I want to be clear that this may be an anti-pattern, per https://xyproblem.info/ in my opinion there is insufficient justification for this and this may not be the right pattern for whatever problem you may be solving

Dustin Getz (Hyperfiddle) 2025-03-13T12:44:56.992349Z

((fn [] ...)) is a much better idiom, because it constrains you to use actual imperative statements (no latency, no reactivity) -- this is 100% sane. Therefore, if your problem can be refactored into an IIFE, i recommend doing that.

2025-03-13T15:55:56.002169Z

@dustingetz Iโ€™ve used it for this kind of thing:

(sequentially
  (check-and-maybe-throw-exception)
  (do-what-i-really-want-to-do))
It feels quite natural to me and it stops the second part running when it will fail, but maybe itโ€™s not good.

xificurC 2025-03-13T15:58:26.684389Z

yes, given the number of users rolling their own it makes sense to include it in contrib

xificurC 2025-03-13T16:02:46.179569Z

there's nuance to the different patterns, e.g. the last one can be

((fn []
   (check-and-maybe-throw-exception)
   (do-what-i-really-want-to-do)))
IFF the 2 fns are clojure(script) fns. If one wants to run a platform effect after an electric call an IIFE still does the trick
((fn [_] (platform-effect)) (Electric-call))
Only if one needs to sequence 2 electric calls one needs case
(case (Electric-call1) (Electric-call2))

๐Ÿ‘€ 2
xificurC 2025-03-13T16:04:21.203049Z

things get trickier if we start adding reactive arguments

Dustin Getz (Hyperfiddle) 2025-03-13T12:36:19.047629Z

https://www.surveymonkey.com/r/getyourdiscount, mention Electric if you want to see an Electric talk

๐Ÿ‘ 4
๐Ÿค˜ 4
๐Ÿค˜๐Ÿผ 1
โœ… 2
danielneal 2025-03-16T18:30:48.582049Z

Done!

danielneal 2025-03-14T11:34:12.822909Z

Is this only for previous conj attendees?

grant 2025-03-14T22:25:00.234259Z

Now if they listen Iโ€™m going to have to figure out making it to the Conj this year. ๐Ÿ™‚

๐Ÿ’ฏ 1
๐Ÿ™‚ 1
Stef Coetzee 2025-03-15T11:56:25.737939Z

@danieleneal don't think so

danielneal 2025-03-15T21:30:16.895609Z

Thanks!

๐Ÿ’ฏ 1