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