[HN Gopher] Why Fennel?
___________________________________________________________________
Why Fennel?
Author : hk__2
Score : 154 points
Date : 2023-09-13 14:21 UTC (8 hours ago)
(HTM) web link (fennel-lang.org)
(TXT) w3m dump (fennel-lang.org)
| robertlagrant wrote:
| > Another common criticism of Lua is that it lacks arity checks;
| that is, if you call a function without enough arguments, it will
| simply proceed instead of indicating an error. Fennel allows you
| to write functions that work this way (fn) when it's needed for
| speed, but it also lets you write functions which check for the
| arguments they expect using lambda.
|
| I don't understand this; why is this a speed consideration?
| munificent wrote:
| Caveat: I haven't used Fennel but just inferring from what
| makes sense...
|
| The Lua VM that they compile to already handles missing
| arguments with some attendant but unavoidable performance cost.
|
| Fennel's own `lambda` form that they layer on top does check
| for missing arguments, but it must do so by generating extra
| Lua code to do those checks. That additional code has a runtime
| cost.
|
| Using `fn` avoids that extra generated code and its cost.
|
| If Fennel had its own runtime and VM, then the performance
| story for how missing arguments are handled would be different.
| iimblack wrote:
| I think they meant speed of implementation.
| mpenet wrote:
| Because it's an extra runtime check vs a direct lua call
| rpdillon wrote:
| I'm not an expert, but my understanding is the Lua has a very
| limited grammar that is specifically designed to be parsed in a
| single pass. This precluded Lua from performing arity checks on
| function calls.
|
| Fennel does support arity checks but it comes with a runtime
| cost since it's implemented as a separate Lua call after being
| transpiled from Fennel.
| vore wrote:
| The grammar shouldn't have anything to do with arity checking
| - at runtime, you're going to know if you passed a function 2
| arguments or 3 arguments, and due to the presence of dynamic
| evaluation, knowing how many arguments a function takes is
| not statically knowable anyway. My best guess is that they
| want to avoid the overhead of a runtime check for arity.
| [deleted]
| sullyj3 wrote:
| It's a runtime check. The following fennel:
| (fn add-1 [x] (+ x 1)) (lambda add-2 [x] (+ x 2))
|
| transpiles to the following lua: local
| function add_1(x) return (x + 1) end
| local function add_2(x) _G.assert((nil ~= x),
| "Missing argument x on /home/sullyj3/tmp/fn-vs-
| lambda/fnl/x.fnl:3") return (x + 2) end
| return add_2
| bnert wrote:
| Arity explanation: https://en.wikipedia.org/wiki/Arity
|
| From the blurb you quoted, it sounds like Lua doesn't check
| function argument arity natively, and fennel can. This means
| that fennel applies a runtime check to validate if a function
| was called with an expected arity, and if not, propagates an
| error (however Lua does that, I do not know), hence why arity
| checked functions are not as performant.
| nmz wrote:
| So it basically does function M(...)
| if select("#",...)>3 then error("failed arity check
| on M()") end end
| ravi-delia wrote:
| pretty much, yeah
| Joker_vD wrote:
| IIRC (and I remember it quite vaguely from some random blog
| post on the Internet) the Lua implementation uses some trick
| that _greatly_ speeds up setting up and tearing down activation
| frames (and has also something to do with the ability to easily
| cross-call into C back to Lua again?), but it hinges on that
| argument-passing /result-returning semantics being "use nils
| for missing stuff, throw away the extras" so e.g. Python can't
| use it to speed up its implementation of function calls.
|
| Unfortunately, I can't find that blog post so take my words
| with a grain of salt.
| throwway120385 wrote:
| This is mostly based on my experience in the past with Lua
| circa 2015 when I developed a GUI using Crank Storyboard Engine
| and needed to write some stuff in C because the Lua equivalent
| code was too CPU-intensive.
|
| If I remember correctly, Lua is a stack-based VM. What this
| means is that every piece of data has a corresponding location
| on a stack data structure in-memory. Function arguments are
| pushed into the stack as-needed and popped in the function
| context, and vice-versa for the function return values.
|
| If you wanted arity-checking in this context, you'd have to
| confirm that you got exactly the right number of elements on
| the stack, meaning there would be an extra branch in every
| function call. This might reduce performance if the branch
| predictor gets it wrong. Plus there would need to be extra
| instructions to count and to check the count for each pop off
| the stack in the context of the function call.
|
| This is from the perspective of calling C functions in Lua, so
| it's probably more complicated for the VM itself when it's
| running native Lua code.
| Verdex wrote:
| Lua is a register based VM.
| neutrono wrote:
| I think he means that the C API is stack based?
| gumby wrote:
| My memory of this is hazy, in part because I wasn't a C
| programmer in those days, but ISTR C used to do this too. I
| think prototypes were added (and required) only by the time
| ANSI got involved.
|
| Maybe some other OF can confirm/contradict?
| ahoka wrote:
| Fun fact: in C, if you have a signature like "int foo()", it
| means any number of arguments can be passed (vs "int
| foo(void)" which means no args).
| fulafel wrote:
| And there is no way for the callee to check the nr of
| passed args, unlike in Lua.
| mdaniel wrote:
| that's ... (amazing|C for ya) int foo() {
| return 0; } int main(int argc, char* argv[]) {
| return foo("alpha", "beta", 1); } $ gcc-13
| -Wall -Werror -o foo foo.c # oh, sads $
| clang -o foo ./foo.c ./foo.c:5:34: warning: too many
| arguments in call to 'foo' return foo("alpha",
| "beta", 1); ~~~ ^
| ./foo.c:5:15: warning: passing arguments to 'foo' without a
| prototype is deprecated in all versions of C and is not
| supported in C2x [-Wdeprecated-non-prototype]
| return foo("alpha", "beta", 1); ^
| 2 warnings generated.
| [deleted]
| astrange wrote:
| No longer true in C23, it means void now.
| sovietswag wrote:
| Good reference for that:
| https://jameshfisher.com/2016/11/27/c-k-and-r/
|
| This was also used to implement variadic functions like
| printf before varargs, see
| https://retrocomputing.stackexchange.com/a/20517
| magicalhippo wrote:
| Because it tastes amazing[1]!
|
| Oh... not the plant...
|
| [1]: https://www.foodrepublic.com/recipes/roasted-chicken-fennel/
| madcaptenor wrote:
| It does! I came in here expecting it was going to be about food
| and was disappointed.
| nultxt wrote:
| Genuinely an incredibly flexible, amazing vegetable!
| Graziano_M wrote:
| I moved my Neovim config to fennel and haven't look back.
|
| https://github.com/Grazfather/dotfiles/blob/master/nvim/fnl/...
| ducktective wrote:
| So basically Emacs with Elisp replaced with Fennel and a more
| responsive UI...
| packetlost wrote:
| Emacs is a whoooooole lot more than an editor and Lispy
| config language.
| thih9 wrote:
| What else is there apart from an editor and a lispy config
| language?
|
| I always thought of emacs as that, i.e. an editor that is
| extensible and dev friendly (in contrast to vimscript). I
| don't know much about emacs though, so this got me curious.
| MassiveBonk51 wrote:
| Well the famous joke is "Emacs is an OS that lacks a
| decent text editor." (Yes Evil mode exists)
|
| Emacs can do basically anything you write an extension
| for it to do. It can be your calendar, your email client,
| your rss reader or even your git gui on top of being an
| editor. Emacs can do so much that it's daunting to start
| using.
| Tao3300 wrote:
| Though it looks and acts like that, and can be used in
| such a way with no problem, in a sense, you've got it
| inside out.
|
| From the GNU Emacs homepage:
|
| _At its core is an interpreter for Emacs Lisp, a dialect
| of the Lisp programming language with extensions to
| support text editing._
|
| It's not an editor with a lispy config language, it's a
| Lispy interpreter that comes with an editor that can
| configure it via said Lisp.
|
| It's kinda like one of those Smalltalk VMs where the line
| is blurred between the code you're writing and the
| environment that it runs in.
| forward-slashed wrote:
| The interactivity is one. It's easy to evaluate
| expressions from within the editor. I am not sure you can
| programmatically change aspects of nvim on the fly, and
| even if so, probably not a central component of nvim
| experience. M-x in Emacs is much more powerful than : in
| (n)vim.
| dinkleberg wrote:
| I've been thinking about doing this, but then reminding myself
| that this is not a wise use of my time lol. However, this looks
| pretty nice. I might have to do it.
|
| Thanks for sharing your setup, I'll be stealing some ideas.
| Graziano_M wrote:
| It was definitely not a good use of my time lol.
| teruakohatu wrote:
| Can nvim read it natively or do you need to transpile it?
| Graziano_M wrote:
| I use a plugin called Aniseed which loads first and does the
| transpiling on the fly for me.
| gorjusborg wrote:
| I linked to aniseed originally, but nfnl is what Olical is
| pointing people toward now?
| gorjusborg wrote:
| You don't need to transpile it if you use
| https://github.com/Olical/nfnl
| delboni wrote:
| If you want a sample nvim setup using nfnl you can check
| this out: https://github.com/rafaeldelboni/cajus-nfnl
| nmz wrote:
| Now I like lua and think single pass is the way to go for
| interpreted, since you don't have the disadvantage of a slow
| compile time no matter how big your codebase gets, BUT its not
| great to write in. some things are (apparently) not possible,
| which means the only solution is to transpile into it, which has
| led to some good languages like moonscript[0], and the dynamic
| nature is a boon as your codebase grows, which has led to teal[1]
| which offers static type checking.
|
| [0]: https://moonscript.org/
|
| [1]: https://github.com/teal-language/tl
| user3939382 wrote:
| > is a boon
|
| A boon is a good thing. I think you meant a problem?
| agalunar wrote:
| Perhaps they had in mind "bane".
| speps wrote:
| Don't forget Terra as well: https://terralang.org/
| stonemetal12 wrote:
| In there it says Lua uses 'for' for looping over integer ranges
| and object ranges. They didn't like that so they broke it up so
| that for is for integer ranges and each is for object ranges.
|
| That seems strange to me. A range is a range so why have
| different ways to iterate over ranges based on what type of range
| it is?
| giraffe_lady wrote:
| I mean it is lua that has two different ways to loop, with
| different syntax and semantics, but calls them both "for."
| "Numeric for" and "generic for" are the official names, with
| separate pages in the docs. Having different names for them
| seems like a reasonable and not that surprising choice.
| Rochus wrote:
| There are quite many languages compiling to Lua (or LuaJIT).
| Fennel is just one of them. See e.g.
| https://github.com/hengestone/lua-languages.
| iLemming wrote:
| What makes Fennel a bit different is that it is a Lisp inspired
| by Clojure. If for any reason neither of these ever interested
| you, then, yes, Fennel would not feel any different to you.
| Rochus wrote:
| The referenced list seems to include a language for every
| taste; Fennel is also there as one of ~10 Lisp variants.
| rcarmo wrote:
| Funny thing, I was looking at Fennel and Lua game engines... Just
| updated with a few: http://taoofmac.com/space/games
| dang wrote:
| Related. Others?
|
| _Language Showcase: Fennel_ -
| https://news.ycombinator.com/item?id=32349491 - Aug 2022 (2
| comments)
|
| _Fennel: A Practical Lisp_ -
| https://news.ycombinator.com/item?id=31029478 - April 2022 (85
| comments)
|
| _Fennel - Lisp in Lua_ -
| https://news.ycombinator.com/item?id=24390904 - Sept 2020 (112
| comments)
|
| _Fennel - Lisp in Lua_ -
| https://news.ycombinator.com/item?id=18016168 - Sept 2018 (62
| comments)
| uwagar wrote:
| because its good for digestion
| iLemming wrote:
| If you're using a Mac, maybe check this out
| https://github.com/agzam/spacehammer
| sdfghswe wrote:
| I didn't realize lua was a proper language until I learned that's
| what factorio uses for its mods.
| dgb23 wrote:
| It's a very common language to embed in video games as a
| modding and configuration tool.
| SoftTalker wrote:
| And that's the sort of thing it's _meant_ to do.
|
| Tools have their strengths. Use them for that. Don't try to
| drive a nail with a screwdriver.
| whalesalad wrote:
| this is a very vague statement. lua is used in a lot of
| environments and is very performant. you can use it inside
| nginx (openresty) to process requests at a pretty large
| scale. you can use it inside of redis.
|
| lua and javascript are somewhat interchangeable aside from
| the fact that js has a much larger ecosystem.
|
| sure there are situations where lua might be a bad choice
| but based on your remarks you make it sound like it sucks
| anywhere except inside a game engine.
| giraffe_lady wrote:
| I always say this when it comes up but fennel is very very
| impressive as a language project. Lua is much beloved but my
| professional experience is that working with it gets gnarly much
| faster than most other languages. Fennel focuses on a small set
| of the worst lua issues and addresses them without getting
| distracted or bogged down in language design extravagances or
| lisp nerd semiotics.
|
| The decision to strictly adhere to lua runtime semantics was
| initially repulsive to me, but I've come to appreciate the
| incredible wisdom of that approach. The practical experience of
| using lua is that because of the constraints of the language,
| every lua runtime is in some ways custom & unique. This decision
| of fennel's creator allows you to drop fennel onto _any_ lua
| codebase, of any version, with any amount of custom freak shit
| grafted in, and just use it. Not only use it, but hook its
| compiler into the lua module loader system, and freely &
| transparently mix functions and tables between the two languages.
| A life raft in decrepit legacy lua codebases.
|
| The restraint and technical focus of this language led to me
| checking out janet, another project of its creator. I've also
| come to _really_ like that language, it makes some similarly
| minor-seeming but brilliant decisions like including PEGs in the
| core lang instead of regex.
|
| Anyway try fennel, if you have to interact with a lot of lua
| pattern match alone will improve your life. Try janet too it's
| cool.
| throwawaypml wrote:
| I think Fennel and Janet went separate ways fairly early on,
| and the creator of Fennel focussed primarily on Janet whilst
| the current maintainer of Fennel is responsible for much
| (most?) of what you see in Fennel today...So some very
| different design choices between the two languages, i believe.
| gsuuon wrote:
| This post inspired me to look for an ML-like language that
| compiles to lua and I found this useful list:
| https://github.com/hengestone/lua-languages
| timetraveller26 wrote:
| I've been wanting to give Fennel a try, currently I use
| Moonscript for my Lua transpilation (https://moonscript.org/),
| but it has some criticisms and it can be a bit confusing
| sometimes.
| JNRowe wrote:
| I'm a _big_ fan of moonscript, but occasionally wish it was
| still be improved and worked on. Yuescript1 looks like it fixes
| most of my bugbears with moonscript, and is for the most part a
| faster2 drop-in replacement.
|
| There was s little discussion here ~18 months ago3, but it will
| feel largely circular if you look as people are suggesting
| fennel there ;)
|
| 1 https://github.com/pigpigyyy/Yuescript
|
| 2 This probably only matters if you have tonnes of moonscript,
| not just a little neovim/mpv/awesomewm config or something.
|
| 3 https://news.ycombinator.com/item?id=29903133
| whalesalad wrote:
| For the clojurists this is a cool intro: https://fennel-
| lang.org/from-clojure
| eviks wrote:
| > yet keeps a very small footprint both conceptually
|
| it's only a benefit for writing simplistic things (and configs
| for some complicated programs like a text editor or a terminal or
| some MMORPG is already not simple), otherwise you start
| appreciating that there is not just a single dictionary as a data
| type etc.
| cheeselip420 wrote:
| Why does every single language landing page not have example
| code? I don't want to read justifications. The code should speak
| for itself.
|
| Show me an echo server. Show me how you open a file and read
| data. Show me SOMETHING. Right on the landing page. How are we
| still doing this?
|
| EDIT: I stand corrected - this is but a subpage. The actual
| landing page apparently DOES have code.
| giraffe_lady wrote:
| This isn't the landing page, which does show a code example
| prominently.
| arvidkahl wrote:
| Linked above is a subpage. The actual homepage at
| https://fennel-lang.org/ has code and even an integrated place
| to run it.
| [deleted]
___________________________________________________________________
(page generated 2023-09-13 23:00 UTC)