[HN Gopher] Extending Emacs with Fennel (2024)
       ___________________________________________________________________
        
       Extending Emacs with Fennel (2024)
        
       Author : Bogdanp
       Score  : 133 points
       Date   : 2025-07-23 05:54 UTC (17 hours ago)
        
 (HTM) web link (andreyor.st)
 (TXT) w3m dump (andreyor.st)
        
       | jhoechtl wrote:
       | What makes a modern Lisp? I am aware of Fennel and Jannet. Anyone
       | havng experience with one of those or another one I am not aware
       | of?
        
         | xlii wrote:
         | Having experience with many IMO it's all about value added.
         | There might be concurrency, message passing (Janet) od global
         | scope isolation (Fennel). Personally I had difficulty getting
         | into Fennel, but no problems incorporating Janet into my flow
         | even though the author is the same. I'm not a fan of hygienic
         | macros though.
         | 
         | I would add Clojure to the modern Lisps, too, which I find the
         | most feature rich (even though had much more blast writing
         | Janet).
        
           | TacticalCoder wrote:
           | > I would add Clojure to the modern Lisps, too, which I find
           | the most feature rich (even though had much more blast
           | writing Janet).
           | 
           | Yup. Clojure may not be the most lispy Lisp but it reaches:
           | it works on top of the JVM (with super easy Java interop), it
           | transpiles to JavaScript and I also use it to write script
           | using Babashka (GraalVM/AOT native Clojure interpreter which
           | starts in milliseconds, avoiding JVM startup time
           | [notoriously slow for regular Clojure programs]).
           | 
           | Being able to share code between Clojure and ClojureScript is
           | really sweet.
           | 
           | Clojure(Script) / Emacs (CIDER) / eglot (LSP client for
           | Emacs): life is good!
        
             | neutronicus wrote:
             | I know the homoiconicity purists hate the additional braces
             | in Clojure, but I consider the literal vectors and hash
             | tables a pretty big win over `#()` and the mess that is
             | dealing with hash tables in CL.
        
               | foxygen wrote:
               | "homoiconicity purists" is probably the wrong term, as
               | Clojure is homoiconic. Probably "Lisp purists" would fit
               | better.
        
         | tmtvl wrote:
         | Common Lisp, which I would consider the most modern, has
         | convenience features which most other languages (even other
         | Lisps) lack. CLOS, macro expansion, and, of course, the
         | condition system.
        
           | terminalbraid wrote:
           | Which lisps lack a macro expansion system?
        
             | tmtvl wrote:
             | R7RS (small, at least) doesn't seem to have macro-expand.
             | R6RS also doesn't appear to have it.
        
               | kryptiskt wrote:
               | R6RS has syntax-case macros which is superior to Common
               | Lisp macros in every respect, they're both hygienic and
               | can be used to implement a sloppy macro system if one so
               | wishes.
        
               | tmtvl wrote:
               | I think we're talking past each other. I mean something
               | like:                 (macroexpand '(when-let (foo (frob
               | bar))           (jib foo)))       ;; (let ((foo (frob
               | bar)))       ;;   (when foo       ;;     (jib foo)))
        
               | ashton314 wrote:
               | `syntax-rules` is very good and you can do a whole lot
               | with them. However, you _are_ limited to template - >
               | pattern transformations, and there are plenty of macros
               | that you cannot write this way. (E.g. anything requiring
               | a predicate on the source syntax that you can't express
               | in the template language, etc.) For that, you need the
               | full power of procedural macros.
               | 
               | Racket improves on Scheme: its macros are fully hygienic
               | whilst not being limited to template -> pattern
               | transforms. See https://docs.racket-lang.org/guide/macro-
               | transformers.html
               | 
               | EDIT: syntax-case -> syntax-rules; R6RS specifies the
               | latter--I believe the former is a Racket construct
               | equivalent in power to `syntax-rules`.
        
               | Straw wrote:
               | I think the parent meant that R6RS has `syntax-rules`,
               | which has enough power to implement CL `defmacro` as well
               | as `syntax-case`.
        
               | ashton314 wrote:
               | My mistake: R6RS has `syntax-rules`, not `syntax-case` as
               | far as I can tell. However, `syntax-rules` and `syntax-
               | case` are equivalent in power. [1]
               | 
               | It does _not_ have the same power as `defmacro`: you
               | cannot define general procedural macros with `syntax-
               | rules`, as you are limited to the pattern-matching
               | language to compute over and construct syntax objects.
               | 
               | [1]: https://docs.racket-lang.org/reference/stx-
               | patterns.html#%28...
        
               | terminalbraid wrote:
               | So the modern scheme specs. (I'd argue putting small in
               | there is unfair considering its intent and the actual
               | implementations of r6rs do offer expansion, e.g. chez,
               | guile, racket)
        
               | soegaard wrote:
               | The name `macro-expand` is from Common Lisp.
               | 
               | Scheme R5RS, R6RS and R7RS all have macro systems. In
               | R5RS has a pattern/template based system (syntax-rules).
               | In R6RS the system has both patterns, templates and
               | procedural macros.
               | 
               | The most modern system is Racket though. See `syntax-
               | parse`.
        
               | ashton314 wrote:
               | [delayed]
        
           | setopt wrote:
           | Do you consider Common Lisp more "modern" than say Scheme or
           | Racket?
           | 
           | As far as I know, the CL spec hasn't been updated for 30+
           | years, and most of its design is far older.
        
             | tmtvl wrote:
             | Don't know much about Racket, but CL has type dispatch:
             | (defmethod join ((a String) (b String))
             | (concatenate 'String a b))       ;; example: (join "abc"
             | "def") => "abcdef"            (defmethod join ((a Integer)
             | (b Integer))         (parse-integer (format nil "~D~D" a
             | b)))       ;; example: (join 123 456) => 123456
             | 
             | And rudimentary support for ADTs:                 (deftype
             | Low-Score ()         '(Integer 0 20))            (deftype
             | Normal-Score ()         '(Integer 21 79))
             | (deftype High-Score ()         '(Integer 80 100))
             | (deftype Score ()         '(or Low-Score Normal-Score High-
             | Score))
             | 
             | (But note that deftypes aren't allowed to recurse.)
             | 
             | CL also has first-class support for debugging with things
             | like describe, step, and trace built-in.
             | 
             | EDIT: Yeah, the CL spec dates from 1994 and a bunch of
             | things which we would expect nowadays (networking,
             | POSIX,...) are provided by external libraries rather than
             | being part of the spec, but in various ways CL is way ahead
             | of its time.
        
             | pjmlp wrote:
             | And yet we're still catching up on having features from
             | Allegro Common Lisp and LispWorks more widespread across
             | mainstream languages, where Java and .NET ecosystems are
             | the closests in terms of IDE capabilities, graphical
             | debugging, runtime introspection, JIT and AOT on the same
             | package,.....
             | 
             | Which goes to show how many lessons the industry failed to
             | learn on those 30+ years.
        
         | radiator wrote:
         | Janet (with one l) is modern because it is, well, new. It
         | doesn't need to carry the historical baggage of Common Lisp. It
         | has many data structures, a concurrency model, it is suitable
         | for functional programming and for object-oriented programming.
         | It has libraries for common tasks and is well documented.
        
           | ritenuto wrote:
           | > Janet (with one l)
           | 
           | Typo, it should be: "with one n" (as the earlier commenter
           | wrote "Jannet"). It took me a while to parse this, I was
           | searching for the nonexistent "l" embarrassingly long.
        
       | psychoslave wrote:
       | Sorry, but what is Fennel?
        
         | Lyngbakr wrote:
         | Fennel[0] is a Lisp-like language that transpiles to Lua. It
         | was originally developed by Calvin Rose (author of Janet[1]),
         | but is now maintained by Phil Hagelberg (author of
         | Leiningen[2]).
         | 
         | [0]https://fennel-lang.org
         | 
         | [1]https://janet-lang.org/
         | 
         | [2]https://codeberg.org/leiningen/leiningen
        
         | ethan_smith wrote:
         | Fennel is a lisp-like programming language that compiles to
         | Lua, offering a more concise syntax while maintaining full
         | compatibility with the Lua runtime.
        
       | tmountain wrote:
       | Fennel absolutely rocks for creating games. It integrates with
       | TIC-80 (open source fantasy console) and also Love (game engine)
       | and PICO-8. Lots of blog articles on getting started. Check it
       | out!
        
         | Kexoth wrote:
         | If so can you reccomend (link here) some of the resources which
         | got you started?
         | 
         | FWIW there are blog posts from the same author of the Emacs
         | setup: https://andreyor.st/tags/game1/
        
           | 3036e4 wrote:
           | I use this for playing with Love2D:
           | https://sr.ht/~benthor/absolutely-minimal-love2d-fennel/
           | 
           | Can't say I made anything worth mentioning. There are some
           | bigger templates available that I am sure do more useful
           | things, but I prefer something small enough that I can see
           | what is going on.
           | 
           | Worked fine even for getting things to run in LoveDOS, a port
           | of some older Love2D version to MS-DOS. In practice
           | compilation was a bit too slow for comfort, so a better way
           | was to pre-compile the fennel-scripts to Lua and just run
           | those.
           | 
           | I installed some LSP server for fennel that comes with
           | optional built-in code completion for both Love2D and TIC-80.
           | Works well in emacs.
        
       | adastra22 wrote:
       | TIL you can configure Emacs with Brainfuck. This is so
       | appropriate and I can't think of a better language to use.
        
         | rayiner wrote:
         | This joke landed better before folks unleashed the horrors that
         | are XML config files.
        
       | campak wrote:
       | came thinking somehow fennel the seed extended Emacs
        
       | anthk wrote:
       | Emacs has cl-lib. If you come from Common Lisp you will be 90% at
       | home, minus closures and a few rough edges. Still, PAIP code has
       | been ported to Elisp:
       | 
       | https://github.com/yfuna/paip-el
       | 
       | The original one:
       | 
       | https://github.com/norvig/paip-lisp
       | 
       | Paradigms of AI Programming:
       | 
       | https://upload.wikimedia.org/wikipedia/commons/d/d4/Peter_No...
        
         | Quitschquat wrote:
         | I thought we had closures now with lexical scope being added in
         | the last few releases
        
           | anthk wrote:
           | Then paip-el should be updated for the latest cl-lib
           | compatibility standards. For sure it would be far less
           | boilerplate code, except for the strings formats of course.
        
       | 3036e4 wrote:
       | Fun project, but I wonder how difficult it would have been to get
       | Fennel to run in Guile-Lua? The article did not get into any
       | details or even mention if it was seriously attempted. Fennel
       | supposedly supports "Lua 5.1, 5.2, 5.3, 5.4, or LuaJIT" so a Lua
       | implementation that is "in the realm somewhere between Lua 5.1
       | and 5.2" is not obviously not supported?
       | 
       | https://fennel-lang.org/setup
        
       ___________________________________________________________________
       (page generated 2025-07-23 23:01 UTC)