[HN Gopher] fe: A tiny, embeddable language implemented in ANSI C
       ___________________________________________________________________
        
       fe: A tiny, embeddable language implemented in ANSI C
        
       Author : sph
       Score  : 149 points
       Date   : 2023-06-08 09:17 UTC (13 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | jacknews wrote:
       | car? cdr? bye!
        
         | zeckalpha wrote:
         | What do you think HN is written in?
        
           | incrudible wrote:
           | Who cares what HN is written in? It could be written in
           | anything. No, I do not buy the Blub programmer argument,
           | either. Yes, maybe literal geniuses are attracted by exotic
           | languages, but genius alone makes for poor business
           | decisions.
        
           | [deleted]
        
           | jacknews wrote:
           | lisp is great, I'm currently learning Janet, playing with
           | fennel and clojure.
           | 
           | But a new 'lispish' should not replicate ancient historical
           | 'accidents', IMHO, and in fact lisp itself should deprecate
           | these names (and caar, caadr, caaaddr ... OMG).
           | 
           | first, rest, or head, tail, or whatever please.
        
             | msla wrote:
             | CAR and CDR can be used to do things other than take lists
             | apart. That's why they have those names.
        
               | jacknews wrote:
               | They have those names because they relate to the
               | registers on the original implementation machine.
               | 
               | time to move on.
        
               | msla wrote:
               | You offer no actual arguments, just pronouncements and
               | irrelevant history.
        
               | jacknews wrote:
               | The argument is the names make no sense, they are purely
               | historical.
        
               | msla wrote:
               | They make perfect sense once you understand what they do.
               | 
               | They're not mnemonic for any specific usage because they
               | have more than one possible specific usage in the
               | language.
               | 
               | Besides, what kind of sense does '+' make for addition?
               | It's also purely historical.
        
               | jacknews wrote:
               | Imagine you were tasked with implementing a linked-list
               | in, let's say 'C', but anything really.
               | 
               | So you choose 'cell' as your name for a node. OK, that's
               | .. fine.
               | 
               | Now you choose 'car' and 'cdr' for each cell's 'data
               | pointer' and 'next-cell-in-list pointer'. How many
               | 'WTF?s'* do you think you'd get in code review? (except
               | from lispers, I guess)
               | 
               | * obviously it's a rhetorical question, no-one writes or
               | says WTF (out loud) in actual code reviews I hope.
        
               | flqn wrote:
               | struct node_t* node
               | 
               | node->data
               | 
               | node->next
               | 
               | Zero "WTF"s
        
               | msla wrote:
               | > Now you choose 'car' and 'cdr' for each cell's 'data
               | pointer' and 'next-cell-in-list pointer'. How many
               | 'WTF?s'* do you think you'd get in code review?
               | 
               | Your names are too verbose.
        
               | [deleted]
        
               | kazinator wrote:
               | John MacCarthy knew that not every computer is an IBM
               | 704, and that users want higher level languages developed
               | on one system to be usable on another.
               | 
               | He stuck with those names because there is no problem
               | with them. They are hard to improve upon in a ways that
               | are only subjectively better while being objectively
               | worse. For instance first and rest are subjectively
               | better for some uses and for some people, while being
               | objectively worse (wastefuly longer for something
               | commonly needed, and falsely associating when the objects
               | aren't used as linear lists). Thus at best we can adopt
               | them as synonyms (and we have).
               | 
               | The were inspired by FLPL ("Fortran List Processing
               | Language"): a Fortran library for list manipulation.
               | FLPL, for mysterious reasons, used pretty horrible names
               | like XCARF and XCDRF. MacCarthy must have been thinking
               | about good naming, because he thankfully dropped the
               | X...F.
               | 
               | I think if they were called something else, I'd still
               | want them to be three-letter identifiers (not just one or
               | two, to avoid clashes) which differ only in the middle
               | letter, so a pattern similar to _cadr_ , _cddr_ ... is
               | possible.
               | 
               | In quantum mechanics there is a <a|b> notation where a is
               | the "bra" and b is the "ket". That doesn't have the right
               | property for _cadr_ , and would be the the target of bra
               | and fig leaf jokes.
               | 
               | In TAOCP, I seem to recall, Knuth calls the fields of
               | binary list cells alink and blink. Not sure if he wants
               | us to pronounce that as blink (of an eye) or bee link.
               | The names are a bit long, but aaabalink is possible. If
               | shortened to alk and blk, that would work.
               | 
               | If both middle letters were vowels, that would be more
               | conducive for the words being pronounceable. That
               | restricts us to aiueo and y. The car using a high vowel
               | is nice, so let's go with i.
               | 
               | How about: dit and dot? The dot is in the ... dot
               | position!
               | 
               | One problem is that cdar becomes doit, which looks like
               | "do it".
        
               | jacknews wrote:
               | "FLPL, for mysterious reasons, used pretty horrible names
               | like XCARF and XCDRF"
               | 
               | It's not mysterious at all, these were also named after
               | the 704 register scheme.
               | 
               | Your argument that MacCarthy et al couldn't think of
               | accurate names may be valid (naming is one of the hardest
               | things, after all), but there are certainly 'better'
               | names, so more likely these just stuck after the initial
               | implementations.
               | 
               | "so a pattern similar to cadr, cddr ... is possible."
               | 
               | Honestly, these are abominations. Remember the point of
               | high level languages etc is not just so you can write
               | code as fast as possible, but that someone else (maybe
               | your future self) can read and understand it easily.
        
               | kazinator wrote:
               | > It's not mysterious at all
               | 
               | By that remark, I'm referring to the X...F dirt in XCARF,
               | not to the CAR infix that we all understand. Why the
               | authors of FLPL saddled the identifiers with that is
               | puzzling. (Extract the content of the address part of the
               | register function? Why?)
               | 
               | Regarding that "R" in _car_ , though standing for
               | "register", refers to a register in memory; Aontent of
               | the Address part of the Register cell.
               | 
               | A piece of memory can be called a register today (e.g.
               | virtual machines have registers that are actually in
               | memory, and some processors have had memory mapped
               | registers like zero page on the 6502). "Content"
               | continues to apply. If someone doesn't like "register",
               | they can pretend it stands for "record". CAR: content of
               | the A part of the record; CDR: content of the D part of
               | the record. The only weird thing are the choices of A and
               | D; the "address" and "data" interpretations don't make
               | sense. But they are just one letter out of three.
               | 
               | Why does it have to be English?                 A =
               | anterieur       D = derriere
               | 
               | In English we use Latin-derived prefixes where A and D
               | form opposite pairs, like: Ascend/Descend;
               | Approve/Disapprove; Adduce/Deduce .. Or cases where we
               | have different roots: Arrive/Depart. Maybe some
               | interpretation can be found.
               | 
               | In Japanese, car and cdr as the verbs "karu" and "kudaru"
               | work. There are several verbs spelled "karu": Yi ru (cut,
               | mow, clip, ...), Jie ru (borrow) and some others like
               | Shou ru (hunt: animals, but also refers to picking and
               | gathering berries and such). Kudaru is Xia ru, to
               | descend. We can borrow/clip/pick the item at this cell
               | (karu) or descend down (kudaru) to the next cell.
               | 
               | Not everyone who codes is a native speaker, yet most
               | languages use English-derived words. Someone to whom "if"
               | and "while" are foreign words may not care about some
               | English speakers nitpicking over car and cdr.
               | 
               | > _can read and understand it easily._
               | 
               | If you accept (car (cdr (cdr x))), then (caddr x) is a
               | nice abbreviation for it, related by a transparent naming
               | scheme. The source code is smaller, and if the compiler
               | doesn't automatically reduce (car (cdr (cdr x))) to
               | caddr, you get better code density.
               | 
               | The name doesn't work in a filter pipeline (-> x caddr
               | ...) because the letters are now backwards w.r.t. pipe
               | direction, since they indicate right to left application.
               | 
               | A good way for your future self to understand everything
               | is not to keep changing names every year. The future self
               | of some person coding in 1968 understands (if still
               | alive) code I just wrote in a different Lisp dialect in
               | 2023, because I used (cadr x). It may not be familiar to
               | Lisp outsiders, but it's an utterly unmoving target for
               | insiders.
        
       | Iwan-Zotow wrote:
       | Femtolisp anyone? Use in Julia I believe
       | 
       | https://github.com/JeffBezanson/femtolisp
        
       | frou_dh wrote:
       | Doesn't really count as language design if it's toy Lisp #9368.
       | Language implementation exercise, yes.
        
         | zokier wrote:
         | Who is counting?
        
           | baq wrote:
           | Me, I'm counting!
        
           | frou_dh wrote:
           | Well I counted 0 references to Lisp or Scheme in the
           | documentation, so it seems to be presented as novel.
        
             | kazinator wrote:
             | It has cons cells, and lists terminated by a symbol whose
             | name is nil. It's more of a Lisp than Clojure.
        
             | striking wrote:
             | But then if you call it a Lisp or even mention Lisp, some
             | other wise guy is going to complain that it's not a real
             | Lisp.
        
               | haberman wrote:
               | Even if you don't mention Lisp, people will assume you
               | were trying to make it a Lisp and complain that you
               | didn't follow Lisp precedent. Examples can be found in
               | this very comment section.
        
             | masukomi wrote:
             | When you have methods named `cons` `car` and `cdr` that
             | appear to work in the same way as lisp's methods of the
             | same name it's pretty clear that you're not pretending or
             | attempting to be "novel".
             | 
             | While it _should_ say it's a lisp / scheme, given those it
             | doesn't really _need_ to say that because it's pretty
             | forehead slappingly obvious to anyone who knows what lisp
             | or scheme are.
        
       | kristianpaul wrote:
       | Wondering how it compares to Lua
        
         | zokier wrote:
         | Almost two orders of magnitude smaller codebase.
        
       | [deleted]
        
       | wsc981 wrote:
       | Maybe a little bit offtopic, but rxi also made a few Lua / LOVE
       | 2D libraries that I've been able to put to good use, namely shash
       | [0], lume [1], json.lua [2] and classic [3].
       | 
       | He makes some nice stuff.
       | 
       | ---
       | 
       | [0]: https://github.com/rxi/shash
       | 
       | [1]: https://github.com/rxi/lume
       | 
       | [2]: https://github.com/rxi/json.lua
       | 
       | [3]: https://github.com/rxi/classic
        
       | sirsuki wrote:
       | I once wrote a tiny DSL language. I used LISP (S-Expressions with
       | parenthesis) because it semantically fit and made the parser much
       | easier to write. I was laughed at and ridiculed by my peers.
       | Everyone hated it that I had to attempt two other language styles
       | just to compensate. I had a chuckle seeing fe syntax is LISP like
       | and I was like "See? I'm not the only one." Many just can't give
       | LISP and S-Expressions their due regard. Same for Reverse Polish
       | Notation. I was born on the wrong planet.
        
         | drpixie wrote:
         | I love RPN for calculating - I still regularly use a HP11C
         | (Swiss Micros replica).
         | 
         | But I hate coding or reading prefix (list) or postfix (rpn,
         | forth, etc) languages. Once wrote a substantial project is
         | Postscript - works fine but note easy on the brain.
         | 
         | Guess it comes from just too much familiarity with infix
         | notation!
        
           | nine_k wrote:
           | There are Lisp macros that allow writing infix arithmetics.
           | Even fe is said to support macros.
        
           | packetlost wrote:
           | I personally find prefix and RP notations to be pretty easy
           | to read, but writing is harder for me. I've introduced bugs
           | into FORTH programs because I did a + b instead of a b + out
           | of habit. I think both notations have their place and not
           | everyone will be able to make the switch
        
         | [deleted]
        
         | lelanthran wrote:
         | No you weren't, many of us, like myself, have designed small
         | languages over the years.
         | 
         | After a few of these, you stop designing syntax: you just skip
         | the syntax and directly read ASTs instead of whatever syntax
         | you wasted your time on.
         | 
         | My next language is going to be a FORTH of some type .
        
           | packetlost wrote:
           | I don't think it's worth making a FORTH unless you plan to
           | build an optimizing compiler better than what iForth, gForth,
           | or VFX have done, open source and maintain it, or exclusively
           | target microcontrollers. FORTH is a great "language" but the
           | ecosystem is tiny and the tooling is pretty minimal.
        
             | hoosieree wrote:
             | I thought part of the reason people use forth is because
             | they don't need or want the dependencies and complexity of
             | a big ecosystem or lots of tooling.
        
             | lelanthran wrote:
             | Well, yeah, I hear you.
             | 
             | But consider that I didn't make lisp-like languages because
             | I didn't find anything suitable.
             | 
             | There were (and still are) lots of nice Lisp
             | implementations when I made my variations over the years.
             | 
             | It's the same with any language created by a single person:
             | we aren't doing it so that we can use it in production
             | (that's a bonus, if possible).
        
               | packetlost wrote:
               | Fair enough!
        
           | carapace wrote:
           | I worked with Joy for some time and came to the conclusion
           | that syntax is a MacGuffin.
        
         | cpeterso wrote:
         | John McCarthy had the opposite experience: he originally
         | planned to replace Lisp's S-expressions with a more ALGOL-like
         | syntax called M-expressions, but other people liked
         | S-expressions and he never got around to implementing
         | M-expressions.
         | 
         | https://en.wikipedia.org/wiki/M-expression
        
         | baq wrote:
         | You'd be hailed as a genius if you replaced s-expressions with
         | yaml.
        
       | ideasman42 wrote:
       | Are there any projects using this?
        
         | stevekemp wrote:
         | cel7 is a 60kb framework for making grid-based games limited to
         | 4-bit color ASCII output. The framework is based around the fe
         | programming language:
         | 
         | https://rxi.itch.io/cel7
         | 
         | There is a community edition which can be used, as the original
         | is closed source:
         | 
         | https://github.com/kiedtl/cel7ce
         | 
         | There is also "aq", a small framework for making audio toys:
         | 
         | https://github.com/rxi/aq
        
       | kortex wrote:
       | > Donnie: I made a new language
       | 
       | > Therapist: New language, or LISP dialect?
       | 
       | > Donnie: LISP again
       | 
       | Mostly a dig at the title. Jokes aside, I love how concise this
       | is. Not sure how I feel about readability, too many inline if {}
       | blocks for my liking, and a bit arcane. But I'm never not gonna
       | upvote novel languages. Something about language creation
       | delights me.
        
       | joeatwork wrote:
       | If this project interests you but is a bit more minimal than you
       | need, the Janet language is a slightly-less but still pretty
       | lightweight embeddable Lisp with a strong library and community:
       | https://janet-lang.org/
        
         | rychco wrote:
         | I just started toying with Janet recently & so far it's very
         | pleasant
        
         | schemescape wrote:
         | Has anyone here switched from Common Lisp or Scheme/Racket to
         | Janet? If so, what was good/bad about the switch? Or was it
         | just different?
         | 
         | I recently started learning Common Lisp, and it's been mostly
         | great, but my two complaints are 1) memory usage and 2)
         | deployment (copy source or distribute a relatively huge world
         | image--and I haven't found any way to get a fully static build
         | without patches, even with ECL).
         | 
         | Janet could solve both of those, although I'd pay a performance
         | penalty due to it being interpreted, and I assume there are a
         | lot fewer libraries/tools. I really like the idea of a Lua-
         | sized Lisp, but I'm not sure if I should jump ship from a
         | traditional Lisp yet.
        
           | baq wrote:
           | I've never done basically any lisp except a toy project but
           | this
           | 
           | > distribute a relatively huge world image
           | 
           | in my understanding of the lisp world is actually a
           | feature...?
        
             | schemescape wrote:
             | You're right, it _is_ a feature, but I'd like _the option_
             | to distribute a smaller binary without everything built in.
             | Roswell supposedly helps with this, but I haven't gotten it
             | to work yet. Some commercial implementations support this,
             | I think, but they're priced well beyond my hobby project
             | budget.
             | 
             | Janet is intriguing to me because it has a small footprint
             | (even smaller than most Schemes). I've heard it's handy for
             | building little utilities, especially if you want someone
             | else to be able to run them (a situation I find myself in
             | regularly).
        
           | nine_k wrote:
           | Janet is planned and built as an embeddable language; CL is
           | not.
        
             | schemescape wrote:
             | Absolutely, but it's not even embedding that I had in mind.
             | I want to be able to produce fully statically linked
             | binaries, because in my experience that is the only truly
             | portable binary solution on Linux. It's a trade off for
             | sure, but it's something I've found useful for running on
             | e.g. Raspberry Pi.
             | 
             | For SBCL, the two main approaches I've seen are: a) use a
             | patched version of SBCL that is statically linked or b)
             | build against an old glibc and hope for the best (which
             | sadly doesn't work on my musl libc-based distribution). I
             | guess the third approach is distribute source and compile
             | on the device--this is what I'm actually doing, but it
             | seems a little silly to recompile every time, even if it's
             | the same architecture.
             | 
             | And keep in mind this is just my wishlist of functionality.
             | It's not necessary and I don't expect it, but it would be
             | really convenient.
        
       | ComputerGuru wrote:
       | Here is as good of a place as any to ask: does anyone know of an
       | embeddable scripting language pretty much exactly like Lua but
       | with more C-like syntax?
       | 
       | EDIT: the best alternatives I'd previously found were rhai (still
       | niche and weak library) and sandboxed JS (heavier than I would
       | like and the standard library is still poor).
        
         | schemescape wrote:
         | For JavaScript, did you look at QuickJS? I believe the binary
         | size is in the same range as Lua.
         | 
         | The standard library isn't terribly extensive, but I think it's
         | more comprehensive than Lua, no?
        
         | xlo wrote:
         | Maybe AngelScript?
        
         | alwaysbeconsing wrote:
         | Maybe Wren? It has classes and method syntax too but it's
         | mostly C like: curly-braced blocks, operators are pretty much
         | the same, slash and slash-asterisk comments, if/while/for with
         | parens, ... Statements are not terminated by semicolons,
         | though.
         | 
         | https://wren.io/syntax.html
        
         | avgcorrection wrote:
         | I haven't heard of that. Something that just compiles to Lua
         | would probably be the easiest way to achieve that.
        
         | vitiral wrote:
         | Not exactly the requirements your asking but you might be
         | interested in the language I'm writing
         | 
         | github.com/civboot/fngi
        
       | zogomoox wrote:
       | When I see amazingly compact language implementations like this,
       | the effect on me is not 'I want to use this language' but rather
       | 'I should also write my own LISP'.
        
         | tjoff wrote:
         | I misread it as 'I should write my own LSP [for that
         | language]', which might be neat project too!
        
         | ranger_danger wrote:
         | Strange effect however I kinda felt it too. But alas `#include
         | <setjmp.h>` here be dragons.
        
       | beeforpork wrote:
       | There's also ulisp (for Arduino projects etc.):
       | http://www.ulisp.com/
       | 
       | This is larger, because there are functions for accessing
       | peripherals, and the core is more standard lispy with 'caadr'
       | et.al., and it has a compacting GC, so images can be saved as a
       | compact blob.
        
       | stevefan1999 wrote:
       | Just another LISP clone...
        
         | tm2t wrote:
         | Yes, and? What's wrong with that?
        
           | masukomi wrote:
           | nothing's wrong with another lisp clone.
           | 
           | the problem is with not being upfront about it. The problem
           | is the implication that this is something new, that may solve
           | some new problem in some new way.
           | 
           | Now, it MAY do something other lisp clones don't, but if it
           | does there's zero indication of it in the readme.
        
             | linkdd wrote:
             | "new" when talking about a repository with 15 commits, the
             | last one being 3 years ago.
             | 
             | It is obviously a toy experiment and it took my 5s to
             | realize that.
             | 
             | While it does not say "this is a lisp", it also does not
             | say "this is a new shiny thing that will change the world".
             | In fact, it says nothing except "look at what i did".
        
       | bpierre wrote:
       | Not to be confused with Fe: https://fe-lang.org/
        
         | yebyen wrote:
         | There's an awful lot of languages with an .fe code file
         | extension, aren't there:
         | 
         | https://ferite.sourceforge.net/
        
         | calibas wrote:
         | Also not be confused with ferric oxide: https://www.rust-
         | lang.org/
        
       | bippingchip wrote:
       | I was wondering what the goal of the project is. The README is
       | not very clear on it, but the implementation document [1] does
       | state design goals:
       | 
       | - Small memory usage within a fixed-sized memory region -- no
       | mallocs
       | 
       | - Practical for small scripts (extension scripts, config files)
       | 
       | - Concise source -- less than 1000 loc
       | 
       | - Portable ANSI C (Windows, Linux, DOS -- 32 and 64bit)
       | 
       | - Simple and easy to understand source
       | 
       | - Simple and easy to use C API
       | 
       | [1] https://github.com/rxi/fe/blob/master/doc/impl.md
        
         | jhvkjhk wrote:
         | The author developed some games. Maybe the goal of fe is to
         | write game scripts.
        
         | LeifCarrotson wrote:
         | > - Portable ANSI C (Windows, Linux, DOS -- 32 and 64bit)
         | 
         | I skimmed through the source, and aside from reading a file
         | from STDIN to a `static char buf[64000];`, nothing in this
         | seems to use the POSIX API. With that buffer trimmed to an
         | appropriate length, it appears it could run on a
         | microcontroller, which is always a useful thing to have.
        
       | rurban wrote:
       | = for defun, really? why not set?
       | 
       | = really is for equality in lisp, not assignment
        
         | JonChesterfield wrote:
         | I read (= a b) as unification and slowly pieced together that
         | it was probably assignment. Not as equality as the results of
         | all the expressions starting = were discarded.
        
         | sph wrote:
         | There is no mention of this being a Lisp anywhere in the name
         | or README files.
         | 
         | You are mistaken in assuming that, since it has parens, then it
         | must conform to being a Lisp.
        
         | stefncb wrote:
         | Why is it so strange that someone ignored a convention?
        
           | [deleted]
        
           | maleldil wrote:
           | Because it's a 50-year old convention, and there doesn't seem
           | to be a compelling reason for ignoring it. The language then
           | uses `is` for equality, including numbers.
           | 
           | It's just weird, especially given they're using old-fashioned
           | car/cdr instead of head/tail.
        
             | sph wrote:
             | This is not a Lisp, and never claimed to be one.
             | 
             | This kind of gatekeeping from ANSI Common Lisp purists is
             | tiring. Who cares about convention when one just wants to
             | build their own language, use S-exprs and car/cdr for the
             | sake of it.
        
               | maleldil wrote:
               | > Who cares
               | 
               | Potential users care. It's off-putting to use something
               | familiar but different in strange ways.
               | 
               | Using head/tail versus car/cdr would be a deviation I
               | could understand. This = mess isn't.
        
             | hota_mazi wrote:
             | > Because it's a 50-year old convention
             | 
             | That's a terrible reason to justify... well, anything,
             | really.
        
               | nine_k wrote:
               | It's not just 50 years old, it's _widely conformed to_
               | for these 50 years.
               | 
               | Why won't you use "&" for "less" and "%" for "greater",
               | instead of sticking to the tired "<" and ">"?
        
               | hota_mazi wrote:
               | Slavery was widely confirmed for even longer. Tradition,
               | right?
               | 
               | How about instead of using tradition to decide if
               | something is beneficial or not, you just assess it on its
               | value?
        
               | mojifwisi wrote:
               | > Slavery was widely confirmed for even longer.
               | Tradition, right?
               | 
               | This is an egregious use of the noncentral fallacy.[1]
               | 
               | Conforming to this 50-year tradition makes the language
               | more familiar and easier to learn, so it's reasonable to
               | question why the language chose differently.
               | 
               | [1]:
               | https://www.lesswrong.com/posts/yCWPkLi8wJvewPbEp/the-
               | noncen...
        
       | slmjkdbtl wrote:
       | i always go to rxi if I want to read some good concise c code,
       | every one is worth reading
        
       | vitiral wrote:
       | cool a lisp clone. Good work.
       | 
       | Could macros be used to add structs? How much code would this
       | require?
       | 
       | I don't feel like a language is real until you can associate
       | data. It's literally the first thing I do when I start any
       | software project that's not a five line script
        
       ___________________________________________________________________
       (page generated 2023-06-08 23:01 UTC)