clojure 2026-03-22

Can I compile or interpret clojure code during runtime? I will perhaps want users to configure my web application with clojure code. Or, should I writer a compiler for a sexp-based domain-specific language? It's not a general purpose langauge. It is a very restricted language with a few primitives. Racket is known for easy creation of sexp-based DSLs. Jonathan Blow criticized embedded (general-purpose) scripting languages like lua that are used in game engines. It's got to be a restricted DSL. If the scripting language is different from the implementation language, there will be frictions due to the fact that I have to implement hooks. Or, can I let users write in a scripting environment where a clojure eDSL and a few carefully selected namespaces are injected? Basically, a sandboxed clojure compiler. Most users may be able to grok simple (e)DSLs.

I may experiment with SCI scripts anyway because I found at least two ways to limit execution time and memory consumption on SCI scripts. 1. Launch a dynamically resizing process pool where each process is a node.js process where the node.js process itself enforces a soft memory limit, and operating system enforces the hard memory limit. Each process has 3~5 threads. Each thread handles one SCI script at a time. node.js vm module enforces soft timeout. The master process kills a rendering process in the process pool if it exceeds hard timeout. 2. Launch a dynamically resizing process pool where each process is a JVM process where execution time is limited by the master process that kills processes in the process pool, and the memory limit is enforced by -Xmx option. Each process runs one SCI script at a time. The dynamically resizing process pool can grow to saturate CPU cores and system memory. Node.js has faster cold boot time.

You can with eval, but it's dangerous, as in, the user has access to everything and so unless you trust them fully, ill advised. You can use sci, to have a restricted set that will get interpreted: https://github.com/babashka/sci

I think I can cache SCI evaluation results in database and reuse them for HTML layout. This way, my web apps don't have to pay the cost of SCI interpretation during runtime. I'm thinking of exposing a simple eDSL for hiccup layout and documenting my eDSLs. Something like

(page
  (hero "xxx.png")
  (card "xxx"))
Even non-technical people can learn simple eDSLs. They don't need to learn control structures. It's easy to provide an escape hatch for writing raw hiccup in my eDSL.

While visual editors appeal to low-tech people, they also are difficult to implement and not very flexible.

Ya, if you need something even simpler. It really depends if you want them to have access to pretty much full Clojure or something even more minimal. SCI gives you full Clojure, all you choose is what functions they have access too.

eDSLs are good for hiding the full power of clojure. The power is available, but it is optional. I wonder whether non-technical people will want to write eDSLs or markdown. In any case, I don't have time or resource to implement a visual editor. If wix couldn't create a good visual editor with its resources, neither can I. I think simple eDSLs are the best.

Perhaps, I will even make a SCI eDSL as a substitute for markdown as well.

(article
  (paragraph "Hi, my name is jason.")
  (paragraph "How are you?"))
This looks worse than markdown. I guess I will just use markdown for contents. Or, I can look into embedding clojure eDSL code in markdown contents.

Can't help you there, not sure what UX would be best for your users or what you want to achieve.

What I know is that I can't give them visual editors even if I wanted to, and visual editors are brittle and infiexible anyway. I'd rather give my users a properly constructed half product than a poorly constructed full product. I don't think I can build a usable visual editor in a reasonable amount of time. Perhaps, when I actually have resources or employees, I can consider visual options.

I guess often times eDSL in Clojure are done as pure-data. Like hiccup. You could look into that as well?

Pure data is fine as well. Maybe, EDN. Or, hiccup.

I think I want to follow GNU/emacs/guix philosophy for web development. One unified language for everything from top to bottom. The implementation language is the same language as the user scripting language. Simple limited eDSLs for each part. A unified monolith. My web development platform will also be for web development agencies that want something between wix and building everything from scratch.

I realized that a centralized web development platform is going to be a good leverage when I do web development for clients. When clients just want to change some parts of a page layout, I can teach them the minimum required to tweak the eDSL code I wrote. Perhaps, they have employees who can learn just enough of my web development eDSLs for marketing campaigns. The eDSLs will be easy enough for people who know a little bit of coding. You wrote a few python scripts? Good, you can learn my eDSLs quickly. When clients want to tweak little things here and there without me, limiting programmability is not a good idea, and forcing them to write everything from scratch is also not a good idea. Simple eDSL is a good middle ground. The full power of clojure with loops and functions can be unlocked when necessary. If clients don't want to write even simple eDSLs, they can hire me or someone else. I think simple eDSLs in SCI scripts are a good idea. It's the emacs of web development.

Making it easy to write some SCI eDSL scripts is a good goal.

You could also use hiccup if it supports custom tags

I guess it's better to start with low-level primitives like hiccup.

And it saves you the trouble of sandboxed execution, it's data so easy to persist. Hard to imagine what features you describes can't be addressed by hiccup

If I stat small with giving (custom) hiccup tags to a simple function in an SCI script which pre-renders and caches HTML on JVM, then the power of SCI is available just in case without a lot of burden. No? I can persist SCI scripts in deployments. Vercel persists scripts in deployments. I can inject just one function at the beginning.

Perhaps, I can start with just

(render [:tag1 [:custom-tag2 ...]])
This is not complex. This is basically the same as hiccup, but SCI can be available as an escape hatch just in case.

Or, I can use SCI just for a nicer syntax than pure EDN. No programmability, but just nicer syntax for hiccup pages. Pure nested EDN syntax is not very nice to read. SCI syntax is nicer with parentheses and brackets. A nicer SCI syntax for hiccup entry.

Shopify's liquid template language has escape hatches with control statements like • {% if settings.show_banner %} • {% for product in collection.products %} I think having SCI just in case can be helpful, but I'd start with using SCI as just a nicer syntax for hiccup entry.

Don't let me stop you from making a mistake

What mistake did you make?

I'd recommend starting with data. you can always add on top of it (yes, inb4 sci is just serialized sexprs)

you'd probably want to "compile" everything down to hiccup anyway. start with that and see what's missing only when it's begging to be added as it can't be done differently

What mistake did you make specifically?

I don't know what mistake you made, but I could implement custom hiccup tags that implement basic logic like if, case, and for loop. That's like shopify's liquid template language.

I think you misread my message

💯 1

I would consider https://www.jetbrains.com/de-de/mps/ or an XML tool like https://www.xmlmind.com/xmleditor/ . I normally do such transformations with XSLT. That works really nice, if you can live with the ugly XML syntax.

After thinking this issue through, I decided to stick with custom hiccup tags for as long as possible. It's better to stay as minimal as possible.

💯 1