A year of Calcit-js

Previous context:

Home page http://calcit-lang.org/

Calcit-js was announced more than a year ago. And major change since that time was the refactor into Rust, and it also happened about a year ago.

Dev Experience

I used shadow-cljs for years, so I mainly compare it with shadow-cljs. The pain point of shadow-cljs was it was heavy and slow to start since JVM Clojure. I didn’t use it in the past year so I don’t if it’s faster now.

Calcit-js is extremely fast. Most of my projects are not large, and Rust starts fast. In every recompilation all the namespaces are compiled, it still does not take long(shadow-cljs re-compiles fast I know). Calcit-js supports for macros. However it has very weak support for polymorphism, and lacks many abstractions like in Clojure. It’s kind like a JavaScript dialect in semantics. That’s the reason why it does not spent a lot time analyzing. This is very nice for tiny projects.

example: calcit-js compiling in CI switching to calcit-js · Memorhythm/cross-stitch@021e3cc · GitHub

For hot reloading, it’s handled in Vite. The code emitted is in ES Modules format, not much to worry, Vite just bundles it, hot reloads it. At first there was problems related to macros since I don’t know how to make code stable when macros are used, new code inserted into core file and triggers many extra reloads. But I managed to fix the bug earlier this year, now it hot reloads smoothly most of the time.

Also I need an HUD error message for compilation failures, which Vite does not provide. So in Calcit I added a build-errors.js file for build errors, and use my own library to show it. It works, although not as powerful, however helps in most cases. The downsides is Calcit does not perform a deep analysis into code, it only detects missing definitions and missing variables. Some of the errors leak into runtime, I have to read js code to debug. Lack of sourcemaps is sometimes a problem. But I can bear with it with help of Chrome custom formatter. And most of the code logic is similar to JavaScript since Calcit-js does not do lazy evaluation.

Other downsides are,

  • lack of package management, I have to maintain dependencies with git clone commands, very unfriendly.
  • lack of well maintained GitHub Action, the binary is downloaded from my down server every time. no need to compile but still suffers time downloading binary and git fetching dependencies.
  • weak support for polymorphism. although I didn’t use much it in ClojureScript, but I really not satisfied with my own poor simulation of ad-hoc polymorphism in Calcit.

The language is too simple compared to ClojureScript after all, I can’t expect too much. I can’t underestimate the complexity of ClojureScript. Luckily Calcit would meet most of my need thanks to js interop and Vite.

How about Rust

Calcit has some methods of calling dynamic libraries provided by Rust. However, Rust is statically compared. Calcit could not call Rust functions directly, but need to wrap the parameters into Calcit’s EDN data first. It’s quite inconvenient. Also there’s boring issues in installing and managing dependencies. It’s far from the convenience calling Java from ClojureScript.

So currently there are only a few cases of Rust FFIs in Calcit. However I still feel still lucky that Rust has a huge ecosystem when I do need features from it.

Usages of calcit-js

Thanks to JavaScript interop and ES modules, there are lots of APIs and modules to use from JavaScript world.

I migrated my libraries Respo and Phlox to Calcit-js, which I previously implemented in ClojureScript, and they work well, as libs in scripting languages. Meanwhile I made quite some nice tools and toys with them. A nice piece of them is a tool for rendering kaleidoscope, which is using Phlox(wraps PIXI.js):

and another one is Hovenia Editor, which is an experiment of drawing editable syntax tree on Canvas:

and I have some other interesting shapes created with a three.js Calcit-js wrapper too, if someone interested: Ruled Surface .

Confusing parts

Developing a language could be really heavy work. Besides the packages manager, another huge missing piece of Calcit is the IDE, or language server. Currently I have no idea how to build a useful analyzer for such a dynamic language, not to mention integrating into VS Code or another IDE. Calcit uses its own web based editor, that’s totally another story.

Also there could be some bugs in code generation of Calcit-js, inside macros, and inside compile js. They are not deeply researched and heavily tested, only used in scenarios of scripting. There might be a lot of work to do, however very few are planed. I have no idea where I will lead Calcit-js to. It’s the foundation of many of my tools and toy, so I will maintain it for a long time. But it’s not evolving, I don’t know how to prepare for more scenarios, or making it powerful(comparing with the power of Rust?).

Nowadays I also spend much time in Rust and WebGL. Scripting languages turns out to be only a small part of the task, being glues and boilerplates. I’m also looking for chances in WASM to see if I could still make improvements in Calcit, no clear ideas yet.


a screenshot at this moment when I try to find out why unexpected value is produced from my math code…(and compiled code formatted by Chrome)


Really interesting syntax! Sort of a scriptable middle ground between Clojure and Haskell?

Edit: found that you’ve already discussed this :slight_smile:

1 Like

Added a rough video on coding Calcit program with a plain text editor:

demo project GitHub - calcit-lang/minimal-calcit: try Calcit using plain text editor .

I was going to say that I’m finding it hard to follow without delimiters (parenthesis) and maybe the excessive spacing between everything.

I think for indentation based, pareinfer style is a good halfway. You write using indent, and it fills in the parenthesis, it also forces the code to remain indented, but still allows for one-liners.

I remembered I have an alternative theme in Calcit Editor… what do you think?

comparing to the default theme:

the syntax reminds me of https://www.red-lang.org

red? Red Programming Language: 0.4.1: Introducing Parse

red syntax is really close to lisp but the first item is on the outside and is more general than a function call. its great for constructing ui… kinda like cirru…