me: flower is mostly a normal project also me:
Is there good reasons to want to have top-level sets that initialize at compile/native image build time in your use-case ?
Whats flower?
@didibus I don't understand your question. "top-level sets" are a very normal thing to do in clojure to my understanding? this is documenting that there are some restrictions in flower that do not apply to "normal" programs.
but as an example of a complicated data structure that uses def instead of defn, see the CLI args: https://codeberg.org/jyn514/flower/src/branch/dev/flower/main.clj#L136
in general anything that uses def increases binary size and decreases startup time
Normally it's best practice to avoid any state or IO initialization or code at compile time, meaning no top level def unless the code is pure or won't initialize at load.
yeah for me compile/run time can be across separate platforms and machines so the difference really does matter and so i really do need to do some things at compile time
flower is an application and not a library so as long as my tests know how to live-reload the code i don't really care if it's "best practices"
a lot of those i can move to build.clj but not all of them
I mean, in your snippet you say that people shouldn't do top-level defs without constraints, due to the native image build step. But in general that's the recommendation for Clojure, even without native image. So I was wondering if there are some things you wouldn't want to do in normal Clojure in a def at load time, that you'd want too for native image because it allows native image to bake it into the binary ?
oh i see. not a ton tbh, usually it's the other way where i have to move things from def to defn. this is probably the most interesting one:
(defmacro cfg [condition & body]
(when (eval condition) `(do ~@body)))
(defmacro cfg-not [condition & body]
(when (not (eval condition)) `(do ~@body)))
; dynamic type checking
(cfg *assert*
(info "instrumenting type signatures")
(require
'[malli.instrument :as mi]
'[malli.dev.pretty :as pretty])
(def flower-nss
['flower.spectacle
'flower.cmd
'flower.main
'flower.eval
'flower.defaults
'flower.frontmatter
'flower.hiccup
'flower.utils
'flower.reflect
'flower.repl
'flower.watch])
(mi/collect! {:ns flower-nss})
(mi/instrument! {:report (pretty/thrower)}))
(cfg-not *assert*
(info "type assertions disabled"))PostgreSQL can be... fun.
Replacing f() with (SELECT f()) in an RLS policy can improve performance by multiple orders of magnitude.
f() - 2 seconds.
(SELECT f()) - 3 milliseconds.
What? Why??
quickly begins auditing his SQL
Wait really? Seems sus. But also unsurprising.
I first encountered the mention here: https://github.com/PostgREST/postgrest-docs/issues/609#issuecomment-1522847852
> There is a better way to force pg to execute the app_metadata function only once for the query: Make it use an InitPlan.
But then later in the same thread someone else said that they didn't see any difference: https://github.com/PostgREST/postgrest-docs/issues/609#issuecomment-1523751670
That almost made me skip experimenting on my own, but then I realized that my f() doesn't actually use the data from the table - there's absolutely nothing to index.
Then I also encountered it here: https://github.com/orgs/supabase/discussions/14576
No clue what actually happens, but in my case the difference is drastic.