[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)