Fennel: A Practical Lisp
mattroelle.com
mattroelle.com
As a big fan of both Lua _and_ Janet, I'll just point out that a lot of what makes Janet nice and interesting are in fact inspired by Lua. Tables, fibers (coroutines), prototypes (metatables/metamethods), custom module loaders, a lot of the API, the peg parser (LPEG), etc etc. I understand no language is for everyone, but the influence can be felt throughout Janet if you're familiar with both.
That kind of thing also has a lot of value when you only want to write something once.
I don't use Lua anymore but it has a special place in my heart. I started learning it to use Love2d and then got my first job as a developer out of sheer luck (someone I knew saw a demo of the game I was working on).
Back then, I didn't understand why it is important that Lua is how it is. I just thought it was to make it more accessible, and while that is certainly a consideration, I think the bigger value proposition is trust and the ability to keep the whole language in one's head with very minimal effort.
Other languages that optimize for stability and simplicity are Clojure and Go. Their respective ideas of simplicity are different but have some overlap. Both languages are very attractive and deeply relaxing.
Anything you wrote in JS twenty years ago probably still works. Tooling has changed, but none of that's an official part of the JS language. The language has only some added features that you can opt to not use.
If you're comparing the whole JS ecosystem to the Lua and Fennel languages, well that's not really a fair comparison.
But if you are working in industry and do some front-end programming… You are going to work with the features that other people around you have decided makes their life easier.
It is possible to work with like-minded souls that want to keep JS simple, but it certainly isn’t a given.
And there are examples in the JS ecosystem that prove me wrong to some extent like htmx, which is a small, simple library written in a straight forward style.
But it’s not entirely unfair either. Reading code is an important part of programming. Integration with libraries often too. You can’t just isolate yourself from churn that easily when everyone else doesn’t. Breaking changes, versioning issues, deprecation etc. happen regardless.
I thought Lua constantly broke compatibility between releases. Several posts about this on HN
If you have not tried Elixir I would say it also has these qualities. (In its own way.) It is very pleasant to use.
Being an ANSI standard with multiple cooperative implementations, it's unlikely to change any time soon.
Importantly, Lua is pretty easy to embed in native applications. I haven’t found a Lisp or Scheme as easily-embeddable as Lua(+Fennel).
It’s also a good drop-in replacement for Lua. I write my Hammerspoon config in Fennel, and hopefully my Neovim config soon as well.
The others I haven't tried embedding, but I hear racket is really no fun to embed,but things might have changed with the chez transition.
Racket CS is also quite fast, comparable to Lua or faster (for numeric ops). It also uses rational numbers which makes it useful for exact numeric operations.
https://github.com/jonpalmisc/dotfiles/blob/master/hammerspo...
https://wiki.call-cc.org/embedding
I've even embedded it in Objective-C programs running in iOS (could make OpenGLES calls in the repl and everything).
Full API spec:
https://wiki.call-cc.org/man/5/Embedding
FFI example:
Janet is surprisingly similar to s7 in many ways. I've been keeping my eyes on it as well, I sure hope it continues! Schemes are so flexible that moving from one to another is just not that hard.
NeoVim[0] had a few words on this topic.
0: https://github.com/neovim/neovim/wiki/FAQ#why-lua-51-instead...
Fennel – Lisp in Lua (2020, 112 comments) https://news.ycombinator.com/item?id=24390904
Fennel – Lisp in Lua (2018, 62 comments) https://news.ycombinator.com/item?id=18016168
Neovim Configuration and Plugins in Fennel Lisp (2019, 19 comments) https://news.ycombinator.com/item?id=21676606
Raymarching with Fennel and LÖVE (2019, 3 comments) https://news.ycombinator.com/item?id=24835766
Fennel looks like a gorgeous lisp. I will probably play with it at some point.
There are a few things that might be nice to have, but few of them are worth more platform churn.
It could happen. I’ve been coding more than three decades and I’ve read some real horror stories over the years.
If I were a luajit user, I’d be interested in trying to raise funding to get some more eyes on the source. It’s an engineering marvel, that’s incontestable, but it needs more coverage in case something happens. Even just to make room whenever Mike decides to retire.
I thought cloudflare and Kong would kick back to the community more, but that seems not to be the case.
This is very different than Node + NPM, which you can get set up and going in <5 minutes.
If you need a solid library ecosystem Lua just isn't the best choice.
I use lua a lot and like it fine but the build/dependency/tooling situation is a fucking mess. It exposes you to a lot of the inconvenience of C in the end.
The Lua libraries in these areas are very well maintained.
That said 90% of the time libraries ship as a single lua file and it’s often better to copy and paste it into your project. I have a modified version of lume I like to use floating around :)
This spartan approach to libraries is a strength of Lua.
(ns foo.bar
(:refer-clojure :exclude [print] :rename {print println}))
(print "Should have a newline") print C-x a - println
M-x abbrev-mode inoreabbrev print printlnThat said I dislike JS as a language and the environment is restrictive. The only way to support debugging is console messages or through Safari web inspector. I’d love to do better.
How would something like Fennel work in this context as a replacement for JS & the bridge?
You're going to need that time to invest in switching to Emacs.
Conjure itself is definitely Neovim-exclusive and heavily uses Neovim Lua APIs.
However I think several of the REPL "server" implementations use various independent protocols. Clojure uses nREPL, Common Lisp uses SWANK, etc. So maybe some of that logic (or even the Lua code) can be reused and ported to other editors.
As much as I love Jupyter, the system of starting and connecting to kernels is kind of a pain, and I believe implementing a proper Jupyter client is nontrivial (and often involves calling out to the reference implementation in Python). It is an "N+1" tool that solves the "NxM problem" (like LSP, DAP, and Tree Sitter), but it doesn't have the same adoption as those other tools.
Guile is designed for embedding. But it is vanilla Scheme, which might not be as modern as the Fennel flavor.
Maybe, the Fennel all gets lowered to Lua at build time, so you don't need a (maybe more expensive) Guile runtime? Or, Lua has a more comprehensive library ecosystem?
fennel -c my-fennel-code.fnl
Or you can use the lua package api to automatically load .fnl files via require seamlessly:
local fennel = require("fennel") table.insert(package.loaders or package.searchers, fennel.searcher)
Enjoy!