I want to add first class support for monkey patching in my guest VM. I found :load-fn, but it works purely on strings, and I don’t see a hook to overwrite the SCI state after that function is run. how do you recommend I do this? Should I override require or something like that?
I do always have the option to just append the string of the patch code after the string of the loaded file, since clojure allows overriding defs in source, but I’m not sure if that’s reliable in all cases.
Monkey patching as in changing vars? You can do this in the same way as Clojure using alter-var-root
hm, to be clear, i want to have something like a patches directory that can override the behavior of require, i don’t want to modify the call sites of require
if i could then alter-var-root would work, yes
Do you just want to load everything from patches at startup?
Like several scripts sequentially or can they depend on one another?
that could work. it has different semantic behavior, right? i’m no longer loading things lazily, so some errors will always show up where they wouldn’t have before?
they can depend on each other, just like a normal clojure program
my ideal solution for this would be a hook that runs after each require, but I understand that’s kind of weird and niche for my use case lol
so patches is basically your classpath right? and you have built-in namespaces that people can override or so? can you sketch out a scenario of what you would like to happen when a user does something?
yeah, let me talk about the whole design.
flower is a static site generator that is a library and not a framework. that means that all the things people expect from a framework, like inversion of control ("just write an .md file and run build") and custom markdown footnote rendering are done in "user-space" (the SCI guest environment, not the Graal binary).
i ship that userspace in a hidden .defaults folder and allow you to override it. for example, markdown footnotes are done in .defaults/transformers/markdown.clj and you can override it by creating your own transformers/markdown.clj in the top-level directory.
that works! but it requires file-level granularity: if anything in the default markdown.clj changes, you don't see those changes (or you have to resolve conflicts). i would like to get it down to def-level granularity: people can override just the transformers.markdown/renderers passed to md->hiccup, without having to copy-paste the whole defaults file. to do that i had the idea to let them write patches/transformers/markdown.clj which is patched into the existing defaults by running alter-var-root for each variable defined.
the problem is that there is no place i can insert alter-var-root: if i do it before returning from :load-fn, the namespace doesn't exist yet, and there is not a hook to do it after. i am asking for a hook to do it after.
this is why i was considering just doing a string-append in load-fn, because i don’t think SCI has anything like this currently and i feel bad asking for a feature just for me 😅
> i would like to get it down to def-level granularity: people can override just the transformers.markdown/renderers passed to md->hiccup
Yes, you could just load the original file + append the patches. Or if the original file is already loaded, then you could just only load the patch file
so in :load-fn you could return the proper namespace source + appended patch
that works :) thank you!