[HN Gopher] Lua: The Little Language That Could
       ___________________________________________________________________
        
       Lua: The Little Language That Could
        
       Author : mooreds
       Score  : 137 points
       Date   : 2023-05-28 18:00 UTC (4 hours ago)
        
 (HTM) web link (matt.blwt.io)
 (TXT) w3m dump (matt.blwt.io)
        
       | PicassoCTs wrote:
       | A whole gamer generation has learned to make mods/games with
       | this. (Roblox).
       | 
       | Not javascript.
       | 
       | Not python.
       | 
       | This.
       | 
       | That which educates the young, shapes the future, may the elders
       | like it or not.
        
         | ChristopherDrum wrote:
         | Pico-8 fantasy console uses Lua (a subset of; with
         | Pico-8-specific console APIs). I keep going back to it in my
         | personal projects time and again. I always think, "OK, I'm
         | going to build the next thing in C" and wind up falling back to
         | Pico-8 and Lua.
         | 
         | The in-the-works Picotron will grow from Pico-8's roots and
         | present a full fantasy computer, with an OS, windowing system,
         | etc. and expands Lua support to the full v5.4 language.
        
         | nanidin wrote:
         | World of Warcraft addons as well.
        
           | kitsunesoba wrote:
           | That's where I first encountered Lua.
        
         | epivosism wrote:
         | yep.
         | 
         | Roblox Lua/Luau tutorials on youtube - millions of views
         | https://www.youtube.com/results?search_query=luau+roblox&sp=...
         | 
         | Luau
         | 
         | https://github.com/Roblox/luau
         | 
         | Roblox wrote a superset of Roblox Lua which is way faster
         | https://luau-lang.org/
        
           | kzrdude wrote:
           | nice pointers, that sounds interesting. Have they kept it
           | near-compatible with lua when it comes to how to embed it in
           | a host app? Wondering if they are "competitive" in that
           | aspect.
        
       | rektide wrote:
       | Lua's presence is honestly hugely because it is so easy to embed
       | in other programs. If you needed some scripting capabilities, Lua
       | was the way. Whether it's a webserver (nginx) or editor (vim) or
       | a window manager (awesome), Lua was the easiest & best at hand
       | option to integrate.
       | 
       | There is a huge opportunity, IMO, for more players here. Deno
       | definitely has some good gestures toward a this. Wasm though
       | seems like the likely general heir, and will have many different
       | offerings for how to do that (Deno being one!).
        
         | Blackthorn wrote:
         | I've honestly not found it easy to embed as-is, at least in
         | C++. Getting functions into Lua is a challenge. Sol2 makes life
         | soooo much easier for it.
        
         | vvanders wrote:
         | It's not just that it's easy to embed but it's also tiny as
         | well, I've run it on many embedded platforms. It wasn't until
         | quickjs came along that there was anything even in the same
         | ballpark.
         | 
         | When you factor in LuaJIT[1] and the incredible
         | performance/zero-overhead-FFI[2] it really is a neat language.
         | 
         | [1] https://luajit.org/
         | 
         | [2] https://github.com/dyu/ffi-overhead
        
         | dleslie wrote:
         | Janet is another language that's just trivial to embed, but
         | it's newer so it has less traction.
        
         | alexjplant wrote:
         | > webserver (nginx)
         | 
         | How timely! Right now I'm learning Lapis [1] by building a toy
         | CRUD app that I plan on deploying to fly.io. Lua reminds me of
         | Go insofar as it's a really "dumb" language. You can't get too
         | cute and there are a few powerful abstractions that let you
         | accomplish a lot. Coming from Python (which is an endless
         | horizon of PEPs and build artifact standards and name mangling
         | and kwargs and... well, you get the idea) it's kind of a breath
         | of fresh air.
         | 
         | As for 1-based indexing: it makes more sense. We're all just
         | used to 0-based because that's how C worked. If you stop and
         | think about it early C was really just a veneer on top of
         | assembly and since addressing an array in memory meant having a
         | pointer to the first element that meant that it was arr[0]. We
         | have no need for this decades later.
         | 
         | [1] https://leafo.net/lapis/
        
           | vvanders wrote:
           | Oh you can totally get too cute with metatables. I've seen
           | inheritance/straight-OO(Java/C++ style), component based
           | design, and eventing/message based approaches all with the
           | core primitives that Lua provides.
           | 
           | I think my favorite one was one that used yield[1] with the
           | parameters being the number of frames to resume the execution
           | of the coroutine. That was used by a number of our game
           | designers to write AI scripting that felt close to literate
           | programming(I.E. "move x, look for player, yield 30, if found
           | player, go here, etc). You could build a whole AI state
           | machine that fit into one page of code and was very easy to
           | follow.
           | 
           | [1] https://www.lua.org/manual/5.1/manual.html#pdf-
           | coroutine.yie...
        
           | fanf2 wrote:
           | Years ago I wrote a DNS-over-HTTPS proxy as an nginx /
           | OpenResty module in Lua. The Lua code included a very
           | stripped-down DNS message parser. The 1-based indexes and
           | closed (instead of half-open) intervals were a _massive_ pain
           | in the arse. The code has a tricky mixture of odd and even
           | offsets that would all have been even in C, and it would have
           | been much easier to replace the magic numbers with named
           | constants.
           | 
           | https://github.com/fanf2/doh101/blob/master/roles/doh101/fil.
           | ..
        
         | Rochus wrote:
         | > _hugely because it is so easy to embed in other programs_
         | 
         | Not only; Lua is also an example of excellent language design:
         | a minimum of concepts for a maximum of expressability; it's
         | minimal, complete and elegant.
         | 
         | > _Deno definitely has some good gestures toward a this_
         | 
         | Lua is much leaner, only ~100k machine code. WAMR looks like a
         | better candidate than Deno, but concerning performance and
         | simplicity it has still to catch up.
        
           | qznc wrote:
           | Forth and Lisp/Scheme and TCL are in the same league.
           | However, they are more alien to C programmers, I assume.
        
             | Rochus wrote:
             | TCL, Forth and Lisp are languages with minimum possible
             | syntax, delegating all higher-level concepts to runtime
             | structures and conventions (e.g. which list position means
             | what), whereas Lua for its syntax and semantics inherited,
             | pruned and elegantly integrated the best features of
             | Modula-2 and other languages. It is true that Lua is more
             | familiar to C developers, since they look back to the ALGOL
             | ancestry; but Lua - unlike C - clearly follows the Pascal
             | heritage.
        
           | stefanos82 wrote:
           | I've just used `cloc`-ed Lua repo's entire code base,
           | excluding makefile's and markdown's: 33619 lines in total of
           | C, Lua, and C / C++ Header code; very lightweight code base.
        
             | Rochus wrote:
             | Lua 5.1 has 11'081 SLOC in 32 _.c and 1 '506 SLOC in 23 _.h
             | files (without tests and examples).
        
         | hgs3 wrote:
         | > There is a huge opportunity, IMO, for more players here.
         | 
         | There are quite a few embeddable scripting languages [1]. I
         | think these days it's less common to embed a language mostly
         | because there are good high-level languages that applications
         | can be predominantly written in.
         | 
         | [1] https://github.com/dbohdan/embedded-scripting-languages
        
       | krapp wrote:
       | I've started to view Lua as an extension to C rather than a
       | language in its own right, which isn't really accurate, but
       | reflects how well the two languages complement each other.
        
       | PhilipRoman wrote:
       | I'm surprised people dislike 1-based indexing. I use both types
       | of indexing commonly and never had an issue with it.
       | 
       | The only issue I've come across in practice is lack of immutable
       | tuples that could be used as table keys. I found myself either
       | emulating this with nested tables or creating string identifiers
       | for my multi-valued keys.
        
         | fanf2 wrote:
         | You can also use light userdata for that kind of thing.
        
       | pyjarrett wrote:
       | Wow, I just integrated Lua into a C++ project for the first time
       | last night.
       | 
       | Took <15 minutes to integrate it with the build system
       | (FASTBuild), watched a tutorial video[1], and then in another 15
       | minutes I had it hooked up to configure my application.
       | 
       | [1]: https://www.youtube.com/watch?v=4l5HdmPoynw
        
       | SeanLuke wrote:
       | Let's put aside the god-awful 1-based tables, in 1993, which
       | alone should have killed the language. My big problem with Lua is
       | that it tries very hard to make possible all styles of language
       | to all people, and as a result it is a language with a lot of
       | boilerplate to do any one of them.
       | 
       | For example, consider Lua's OO. The most obvious inspiration for
       | Lua here was Newtonscript, via Self. They're quite open about it.
       | Newtonscript and Self are prototype-style OO languages done well,
       | as opposed to Javascript, which is a prototype-style OO
       | abomination. Lua advertises itself as being able to do prototype-
       | style OO, all you have to do is make some tweaks to its
       | metatables. But while this stuff is baked into Newtonscript and
       | Self, it is an amazing amount of boilerplate to do it in Lua, to
       | the point of parody. https://www.lua.org/pil/16.1.html
        
         | krapp wrote:
         | You're way too triggered by a programming language, dude. Move
         | past it.
        
         | tayistay wrote:
         | On the page you linked, I see four lines of boilerplate in a
         | constructor:                 function Account:new (o)
         | o = o or {}   -- create object if user does not provide one
         | setmetatable(o, self)           self.__index = self
         | return o       end
         | 
         | Doesn't seem so bad. Are you referring to something else?
        
         | daneel_w wrote:
         | Why would you wish the death of a language only because its
         | default index for arrays is 1?
         | 
         | You're not forced to index from 1 and onwards. You can use any
         | range you want to: https://www.lua.org/pil/11.1.html
        
       | akkartik wrote:
       | For the past year I exclusively use Lua for my side projects. And
       | I use it with certain self-imposed restrictions:
       | 
       | * no Luarocks
       | 
       | * no native libraries
       | 
       | More details: http://akkartik.name/freewheeling
        
         | carapace wrote:
         | That essay/software/discipline is awesome!
        
         | iamcreasy wrote:
         | Can you kindly provide a one line explanation as to why no
         | Luarocks?
        
           | akkartik wrote:
           | https://xkcd.com/2347
           | 
           | That way lies npm and left-pad.
           | 
           | Tools encourage behaviors. I avoid tools that encourage
           | behaviors I want to avoid.
        
           | AHTERIX5000 wrote:
           | Luarocks works quite well if the lib is pure Lua.
           | 
           | For native libs it's a wild west and success depends a lot on
           | your environment. Sometimes the lib is being built with
           | -Werror and fails if you're using more recent compiler,
           | sometimes include paths are not resolved correctly using
           | pkgconfig or similar and so on.
        
         | harryvederci wrote:
         | Great talk!
        
       | zephraph wrote:
       | Anytime Lua comes up I'm reminded of John Earnest's Lil scripting
       | language[1]. It's inspired by Lua and Q, built for Decker[2]
       | which is a re-imagined version of HyperCard. Generally though, I
       | love lua for its embeddability and am extremely happy anytime I
       | see someone chatting about integrating it. Modding and scripting
       | in games was a tremendous motivation for me to dig more into
       | programming and these approachable languages are a core aspect of
       | that.
       | 
       | [1] https://beyondloom.com/decker/lil.html
       | 
       | [2] https://beyondloom.com/decker/
        
       | tayistay wrote:
       | I'm currently using Lua as an extension language in my app [1].
       | Users can write their own custom UIs and DSP code. It's great how
       | the Lua interpreter (and LuaJIT) allow you to provide your own
       | memory allocator, so I can preallocate a region and do realtime-
       | safe allocation within it.
       | 
       | [1] https://audulus.com
        
         | iamcreasy wrote:
         | Looks cool. Is there any 5 min intro video introducing the app
         | to the world?
        
           | tayistay wrote:
           | Thanks! There are a couple preview videos on the App Store
           | and lots of stuff on YT: https://www.youtube.com/audulus
        
       | jmclnx wrote:
       | Lua was on my very short list of languages to learn. Will need to
       | revisit that.
       | 
       | Also worth noting, NetBSD has had lua hooks into their kernel for
       | about 10 years I think.
        
         | ok_dad wrote:
         | You can learn Lua in a weekend, easy. The language is
         | ridiculously small, but also ridiculously powerful. You can
         | learn how to use C libraries in Lua in another weekend, easy.
         | Using Lua from C is also easy, one weekend or less.
        
           | stefanos82 wrote:
           | How about in 15 minutes lol ?
           | https://tylerneylon.com/a/learn-lua/
        
         | celaleddin wrote:
         | Just curious: Can you share your list of languages to learn?
        
       | thangalin wrote:
       | The ConTeXt typesetting system tightly integrates Lua. One aspect
       | of Lua I dislike is that it isn't object-oriented. What's
       | impressive is that the language can be extended to be so in
       | astonishingly little code:
       | 
       | * https://github.com/kikito/middleclass/blob/master/middleclas...
       | 
       | Using OOP, typesetting a hexagonal grid and a symbolic
       | representation of a neural network on top is easier develop, IMO.
       | 
       | A vertex defines a point in 2D space:
       | 
       | * https://github.com/DaveJarvis/keenwrite-themes/blob/main/bos...
       | 
       | An edge connects two vertices:
       | 
       | * https://github.com/DaveJarvis/keenwrite-themes/blob/main/bos...
       | 
       | A graph connects edges:
       | 
       | * https://github.com/DaveJarvis/keenwrite-themes/blob/main/bos...
       | 
       | A priority queue serves for ordering edges by weight of adjoining
       | vertices:
       | 
       | * https://github.com/DaveJarvis/keenwrite-themes/blob/main/bos...
       | 
       | With these concepts in hand, we can typeset a grid and a "neural
       | network" on top:
       | 
       | * https://github.com/DaveJarvis/keenwrite-themes/blob/main/bos...
       | 
       | Here's an example of the output from the first chapter:
       | 
       | * https://i.ibb.co/19DCDZy/ch-1.png
       | 
       | And a later chapter, where the "network" has grown in complexity:
       | 
       | * https://i.ibb.co/ncf16vg/ch-2.png
       | 
       | This is for my near future hard sci-fi book on AGI. I'm looking
       | for alpha readers to give me feedback. See profile for contact
       | details.
       | 
       | P.S.
       | 
       | There's a subtle bug in the code that can result in one or two
       | disconnected vertices. If you spot it, let me know!
        
       | taylorius wrote:
       | Arrays start at 1. Just... no.
        
         | huimang wrote:
         | Very insightful discussion.
        
           | taylorius wrote:
           | Thank you. I'm here all week.. :-)
        
         | josephcsible wrote:
         | Yeah that's a wart, but it's basically the only wart in an
         | otherwise amazing language.
        
           | fbdab103 wrote:
           | Ehh, local being a keyword (instead of local default, global
           | only if required) was a significantly bigger gaff. The other
           | would be no nulls in tables. 0/1 based indexing is
           | familiarity only.
        
             | josephcsible wrote:
             | Requiring a keyword to declare a variable is a good thing.
             | Otherwise, it'd be easily to accidentally declare new
             | variables when you meant to assign to an existing one.
             | Since global is the default, starting a program with
             | something like this effectively keeps that from happening:
             | local gindex = {}       setmetatable(_G, {__index =
             | function(t,k)         local v = gindex[k]         if v ==
             | nil then           error("Bad read of global variable " ..
             | tostring(k), 2)         else           return v         end
             | end, __newindex = function(t,k,v)         error("Bad write
             | of global variable " .. tostring(k), 2)       end})
             | for k,v in pairs(_G) do         gindex[k] = v
             | rawset(_G, k, nil)       end
        
         | ok_dad wrote:
         | Why? 0 based indexing came from a time where you used memory
         | addresses directly to index into arrays. Today, we don't do
         | that, so 1 based indexing seems extremely reasonable. Besides,
         | with Lua you can still do 0 based indexing with a small
         | personal extension function.
        
           | imbnwa wrote:
           | One of the first things requested by users of an internal
           | media sequencing tool where time is measured by frames was
           | 1-based indexing, they absolutely hated starting from 0
        
             | ok_dad wrote:
             | Yea, I love how 0 indexing is such a big deal. Like tabs vs
             | spaces, it doesn't matter even a tiny bit, it's like a
             | religion. It's not that hard to index off of 1, and like I
             | said, you can write like 5 lines of code to make 0 indexing
             | the default!
        
         | krylon wrote:
         | From an aesthetic perspective, I agree. In practice, it wasn't
         | a problem, though. I rarely accessed arrays with a constant
         | index anyway.
        
           | bryanrasmussen wrote:
           | maybe I'm being dim but what possible aesthetic benefit does
           | it offer? The only benefit that springs to my mind from a
           | language design perspective is that it is most likely
           | familiar to the user of the language from languages they have
           | used before.
           | 
           | Both Smalltalk and APL use 1 based indices so I just find any
           | claim of obvious aesthetic superiority on this issue a little
           | hard to accept without some back up.
           | 
           | If speaking aesthetics the fact that the number of items in
           | your array is equal to the position of the last index item in
           | the array would seem aesthetically superior.
        
       | ok_dad wrote:
       | One of my favorite projects that uses Lua is
       | 
       | https://redbean.dev/
       | 
       | It's a single file web application engine, and more, in an
       | executable you can run on several OSes and I think even bare
       | metal, but it's been a while since I looked at it so it's
       | probably even more awesome today.
        
         | rlawson wrote:
         | Yes! I'm currently learning Lua now just because of redbean.
         | 
         | I also recommend the excellent ZeroBrane IDE -
         | https://studio.zerobrane.com/
         | 
         | As a Java/Python dev there is something about using such light
         | weight and _fast_ tools like redbean, lua and ZeroBrane that
         | brings a smile to my face.
        
       | MarkusWandel wrote:
       | I once read through the entire Stroustrup C++ book and figured in
       | one case, there is absolutely no way to make this work except for
       | a secret, hidden variable in the class. Did a test compile and:
       | There it was! OK, I get C++, done. Then I saw actual C++
       | programs. Whoa, how do you index into an array using a string?
       | You don't of course, you overload the [ ] operator.
       | 
       | Reading about Lua when it was newer I could foresee the same
       | thing happening on steroids. Yes, the language itself is simple
       | but what you can do with it - emulate almost any construct in any
       | language - promises confusion. When it comes to readable code,
       | sometimes "less is more" in terms of langauge features.
        
         | notacoward wrote:
         | > OK, I get C++, done.
         | 
         | > ...
         | 
         | > When it comes to readable code, sometimes "less is more" in
         | terms of langauge features.
         | 
         | Please tell me that is meant as satire. There is no sane way to
         | look at C++ and Lua and decide "less is more" would favor C++.
        
       | andrewmcwatters wrote:
       | It is inevitable that people complain about Lua's 1-based
       | "tables" which serve as both arrays and hash maps.
       | 
       | I usually encourage people to remember the practical origins of
       | 0-based arrays when thinking in terms of pointers, where 0-based
       | counting is useful in terms of talking about offsets from a point
       | in memory, as contrasted to 1-based counting where you are
       | primarily talking about quantities of collections.
       | 
       | Lua is a great language. My only wish is that it was easier to do
       | multithreaded work in it. Unfortunately, this is not the case
       | without some significant architectural forethought.
        
         | cyberax wrote:
         | The problem with 1-based arrays is that it makes the offset and
         | location be different. For example, we want to place an item
         | into a simple circular buffer with zero-based indexing:
         | 
         | arr[idx mod capacity] = 123
         | 
         | Now with 1-based indexing:
         | 
         | arr[(idx-1) mod capacity + 1] = 123
         | 
         | This is absolutely makes it a PITA if you're working with
         | things like bitmaps, blending, or sound mixing. If you only
         | need a language for high-level scripting, then it indeed is not
         | such a big deal.
        
           | teamonkey wrote:
           | Lua's arrays can start at index 0 if you like, there's no
           | real reason why the first line wouldn't work.
           | 
           | Starting at 1 is a convention:
           | 
           | array = {"hello", "world"}
           | 
           | print(array[1]) --- displays "hello"
           | 
           | array[0] = "why"
           | 
           | array[2] = "there"
           | 
           | for i=0,2 do print(array[i]) end --- "why" "hello" "there"
        
         | saurik wrote:
         | The reason why 0 makes sense for pointers isn't due to some
         | arcane implementation detail of programming but because of how
         | one conceptualizes ranges and distance and pointers just so
         | happen to be a place where that comes up very directly in
         | programming. Any time you attempt to develop an algorithm that
         | needs to think about multiple ranges of a collection at the
         | same time or needs to scale ranges through a collection,
         | 1-based indexing causes you to have to throw in a bunch of +/-1
         | compensation factors to prevent you from double-counting or
         | scaling past an edge. Life is just too short to have to
         | constantly debug the issues that come from 1-based indexing
         | when developing complex algorithms, even if it means beginners
         | feel a bit confused by "counting from 0".
        
           | andrewmcwatters wrote:
           | No, it actually does originate from 1960's era programming
           | practices. Not to say there weren't also 1-based or N-based
           | numbering, but you're historically misled here.
           | 
           | You could also say the same about counting collections. No
           | regular person counts 0... 1... 2... 3... and ends counting
           | N-1. It, too, is a workaround.
        
             | kzrdude wrote:
             | I don't think saurik is talking about history, so you're
             | talking past each other in that sense.
        
               | andrewmcwatters wrote:
               | I think so, too, but my point is that it makes sense for
               | other historical reasons--not the one the poster
               | mentions. Those decisions weren't made due to
               | mathematics.
        
             | adfgoinionio wrote:
             | [dead]
        
           | hypertele-Xii wrote:
           | If the 1st element is [0], something's conceptually wrong.
        
             | adfgoinionio wrote:
             | [dead]
        
         | verytrivial wrote:
         | Dijkstra had an opinion on this (and many other things).
         | 0-based ftw.
         | 
         | https://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF
        
         | fosk wrote:
         | Yes that is annoying the first week, then you get used to it.
         | 
         | If the biggest complaint about Lua is 1-based tables, I'd say
         | that's a compliment to the language indeed.
        
         | charlieyu1 wrote:
         | The difference between 1-based and 0-based indices is
         | irreverent enough, that's the reason it feels uncomfortable for
         | choosing to use something that is different. It is like little-
         | endian vs big-endian, but you never see people choosing to use
         | big-endian now
        
       | imbnwa wrote:
       | Lua metatable > JavaScript prototype
        
       | squarefoot wrote:
       | Lua was born in 1993. That's 30 years, not bad for a language
       | that some still consider new.
       | 
       | For those looking for a GUI library for Lua, check out TekUI.
       | http://tekui.neoscientists.org/index.html
       | 
       | I tested it on various distros without hassle, both on x86 and
       | ARM. It would probably be worth of porting to other languages
       | too.
        
       | ValtteriL wrote:
       | Lua is also the language of choice for the nmap scripting engine.
       | 
       | While cute, easy to learn and all, I feel like it has kept back
       | the development of nmap scripts. Only a few people are dedicated
       | enough to take the time to learn it.
       | 
       | Then again, I think this has kept the quality of the available
       | scripts high.
        
         | nottorp wrote:
         | Well who knew nmap has a scripting engine? :)
         | 
         | Before reading your post, if i were in a situation where I
         | needed to do complex stuff with nmap, i'd just integrate it in
         | a script that would run it multiple times, parse the output
         | etc.
         | 
         | I never imagined it had a scripting language inside itself.
         | 
         | Guessing the only people who know about that are admins in
         | large networks and black or white hat crackers...
        
         | anony23 wrote:
         | What are some of the nmap scripts that you use regularly?
        
       ___________________________________________________________________
       (page generated 2023-05-28 23:00 UTC)