[HN Gopher] Lua, a Misunderstood Language ___________________________________________________________________ Lua, a Misunderstood Language Author : todsacerdoti Score : 76 points Date : 2021-01-15 21:35 UTC (1 hours ago) (HTM) web link (andregarzia.com) (TXT) w3m dump (andregarzia.com) | virtue3 wrote: | As someone that worked on LuaJIT for embeded devices (IE phones), | I have some strong opinions / context. | | Lua is designed to be small and portable and highly embeddable. | It's not the greatest language in the world, but understanding | it's interpreter and how to use it from your system side is | pretty easy as these things go. | | It's really REALLY well suited to be embedded into whatever | system you need it in. The whole runtime is like nothing. | | And it runs damn fast for an embedded language, there's like 10 | opcodes or something? compared to pythons 100+ (at the time we | did the comparison like 10 years ago). | | Further context, I think we ported our android luaJIT to windows | phone 7 in like, a day? It was super trivial. | monocasa wrote: | I count around 100 opcodes for luajit as well. | | http://wiki.luajit.org/Bytecode-2.0 | | Not sure why reducing the number of ops by an under of | magnitude would make it go faster. | lrossi wrote: | Empirically, it is much faster than Python, but I don't know | either if the opcodes have anything to do with it. | monocasa wrote: | Right, but reducing the number of ops wouldn't get you | there, that just adds more branches in the critical path as | the same amount of functionality needs to be overloaded. | mobilio wrote: | Lua it's very popular on routers because it's using on some | device vendors like Linksys and some opensource distributions | like OpenWRT | [deleted] | noizejoy wrote: | I've discovered Lua only very recently as it has a good presence | in some music making applications for scripting e.g. for the | Steinberg HALion sampler/synth and for Native Instruments Creator | Tools. | | And more recently I bumped into the interesting VST/AU plugin | called protoplug[1], which makes it easy to experiment with | coding audio and midi event processing inside a DAW. | | [1] https://www.osar.fr/protoplug/ | austinl wrote: | Oddly enough, Lua was my first introduction to programming. I was | into Valve's Half Life games and Garry's Mod, and Lua was | typically the way that you'd make modifications to things (e.g. | increase player movement speed). That would interact with the | Source engine, which was in C++, but you could do a lot of stuff | without ever touching C++ [1]. | | I didn't even really think of it as programming at the time. You | start by just changing constants, like what if we make gravity = | 2 instead of 9.8 m/s2? And then build up from there. I think is | what a lot of these educational programming games try to | replicate today. | | After a while, I got confident enough to the point of trying to | do things in LOVE, which is a free and open-source 2D game engine | that uses Lua [2]. What I learned there is the reason why I | eventually studied computer science in college. That said, when I | return to Lua, it feels a bit limited, but I suppose that's the | point! I never really questioned it at the time. | | "Lua is not object-oriented. That is it." Laughed out loud when I | read this. It was funny to learn programming without the concept | of classes, and then realize that Lua is the exception, not the | rule. | | [1] | https://developer.valvesoftware.com/wiki/Embedding_Lua_in_th... | [2] https://love2d.org/ | deergomoo wrote: | Lua was mine too, also via games. I'd installed custom firmware | on my PSP and after getting my fill of emulators and rampant | piracy, I wanted to see if I could make a game. Getting the | C-based toolchain working was far beyond 12yo me at the time, | but there was a "Lua Player" homebrew application that would | load scripts off the memory stick. | | I didn't get far with it and to be honest I remember very | little, but it did set me off down the rabbit hole of learning | to program, and now it's both my career and a big passion. | andrewmcwatters wrote: | Thanks for linking my article. I went on to go build Half-Life | 2: Sandbox as an open-source competitor to Garry's Mod, and | later Planimeter's Grid Engine, which is also based on LOVE.[1] | | [1]: https://www.planimeter.org/grid-sdk/ | d--b wrote: | As a dev who's only tried Lua for a small dev project, I have to | agree with the no-batteries argument. It is so bare that i ended | up implementing tons of function that i wished were there in the | first place. | | Not asking for lua to become the new javascript but a library | like "lodash for lua" would be appreciated... | dividuum wrote: | There's https://github.com/danielmgmi/lodash.lua :-) | | And also https://luafun.github.io, which probably has | overlapping functionality and is optimized with regards to | LuaJIT. | epage wrote: | > Complaints about 1-based indexing for arrays | | I think this misses the point, at least for my case. It doesn't | matter which is technically better. What makes more sense for | humans is a matter of application (and even "non-dev" stuff | varies as to which is better). | | For me, my big concern about using Lua in my products is | | - I expect other developers to be writing the Lua scripts | | - I expect the developers to be frequently using 0-indexed | languages | | In this scenario, "being different" means you are likely to run | into off-by-one errors. Think of that crufty Perl script you | might have around at work where people avoid touching it because | no one is comfortable enough with Perl. Having predictable | semantics helps a lot in scenarios like this. | phaedryx wrote: | There are only two hard things. | | This is an aside, but I think that "index" is the wrong name. I | wish that "index" meant you start counting at 1 (which everyone | outside of CS does) and "offset" was the name for starting at | 0. | nvader wrote: | 1ndex and 0ffset. I like it. | d3ckard wrote: | I _love_ what you did here. Great mnemonic! | Pet_Ant wrote: | I think I will intentionally start using this usage. Maybe we | can make it a thing. I mean we already have argument & | parameter for similar things to make a distinction. | zajio1am wrote: | > (which everyone outside of CS does) | | In set theory (math foundations), ordinals also start at 0. | mumblemumble wrote: | So, I don't do a lot of Lua programming - basically just having | fun with Pico-8 on occasion - so I can't say I have a _lot_ of | experience with this. Every single other language I use starts | at 0. | | But what I have seen is that, starting from 1 felt weird to me | for approximately 1 hour, tops. After that, it was no more or | less of a switching challenge than switching between semicolon | languages and non-semicolon languages. In other words, no big | deal. And, once I got over it, I was pleasantly surprised to | find out that I actually have _fewer_ off-by-one errors in Lua | than I do in other languages. Because the author is right: No | matter how much professional experience I have starting with 0, | starting with 1 is still the more innate way of thinking. | | Also, my single biggest all time source of off by one errors is | translating between mathematical notation and code in a 0-based | language. That fact alone is cause for me to hope that Julia | might one day supplant Python for data work. | bsder wrote: | I'm glad that's true for you, but my personal experience | suggests otherwise. Dijkstra also mentions the Mesa | programming language which had all four of the conventions | and that other than 0-based, half-open leads to errors. See: | https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/E. | .. | | And for those claiming the world is 1-based, they're full of | it. Machining measurement, for example, is _ALL_ 0-based. And | we 're talking a field that has multiple standards for | _everything_ and yet they converged on 0-based measurement. | | The bigger problem, though, is that I even have to use array- | based indexing to iterate something. That's just asking for | bugs. | | And, my favorite question for people who like 1-based is | "Given index n, how do I create index n-1?" | | The answer, of course, is newindex = index - 1 % N. | | The question is, of course, a trick because the answer is | _really_ : newindex = (index - 1) % N. | | Yeah, no. I'll stay in my 0-based languages thanks. | | Side Note: I have other objections to Lua. The big one being | that it's not _really_ compatible between Lua installations. | Everybody compiles different modules so Lua becomes neither | small nor is it the same language between any two | implementations. | brundolf wrote: | Agreed. 1-indexing may be more intuitive for humans broadly, | and this may have been a good argument before C became | ubiquitous, but when it comes to programmers 0-indexing is a | deeply ingrained habit and the landscape of what's intuitive is | different. Very few norms are so universal across programming | languages as 0-indexing | d3ckard wrote: | That's more dependent on language syntax IMO. When you have | traditional C-style loops, maybe. When you use ranges, | iterators etc. it doesn't make any difference. | berkut wrote: | Yep, I think consistency is key here... | | Especially when it's used as an embedded language in a C/C++ | app, or an additional Lua API alongside other APIs that exist | already. | | Having to convert back and forth between 0 and 1 based indices | is very annoying, and error-prone. You can make helper methods | to abstract _some_ of it, but that only gets you so far, and it | 's annoying (at least I found it that way) having to context | switch your brain depending on what part of the call stack | you're looking at. | noizejoy wrote: | It doesn't miss the point, because the point was that non- | developer humans will do better with 1 based indexing. | | Side note: As a former developer, turned regular human being | who scripts from time to time, I don't find switching between 0 | based and 1 based indexing particularly intellectually taxing. | TulliusCicero wrote: | Yeah I have a bunch of complaints about the language that I | developed while learning it and simultaneously teaching my 9 | year old kid, but the 1-based indexing isn't one of them. | That's totally fine, and certainly easier to grasp for a | beginner. | | But there's certainly other stuff that's just weird and bad, | and I think just the fact that it's dynamically typed made it | harder for him to build an accurate mental model -- sometimes | he didn't even realize that an identifier that he had typed | in earlier was a variable, let alone what kind of value it'd | be holding. | billfruit wrote: | Wait till you need to use a formula which has somewhat | complex uses of indexes like 2^(2n+1) and see how having deal | with them in 1-base indexing in addition to 0 based indexing | makes it add bit of unnecessary confusion. | craftinator wrote: | It's not an intellectually challenging context switch, which | is actually what makes it such a problem. You don't have to | think about it, because it's so simple and easy, so sometimes | you won't even think to do it. | zajio1am wrote: | Well, i started programming in Pascal (with 1-based indexing) | and later switched to C. I remember that after switching to C | off-by-one errors magically disappeared. | remram wrote: | Doesn't it bother _you_ as the person writing both the | application and the original scripts, to be using both styles | at once in the same product (sometimes to refer to the same | data)? Nevermind the end-users ' additions. | TulliusCicero wrote: | Sounds like the author is talking about me. | | I'm a programmer who recently started teaching his 9 year old son | Lua, so that he can use the Undertale fan game platform Create | Your Frisk. It's gone okay, but there are things about the | language that just seem weird and annoying and counterproductive. | | For example, tables are very important in Lua as a sort of all- | purpose data structure, that's cool and all, but why is there no | built-in copy function? The author of this article seems to be | hinting that this anti-batteries-included style grants some sort | of freedom to do it myself, which is just kind of silly. I don't | want to do it myself -- and there's a good chance I'd cock it up | if I tried -- my son certainly isn't going to do it himself, and | even if they had provided such a function, that doesn't actually | stop anyone from doing it themselves anyway, if they want to. | | Or, why are there not only no increment operators like ++, but | even no operators like +=? "counter = counter + 1" isn't only | longer to type, it's harder to quickly parse. Why is the standard | style for multiword identifiers neither camelCase nor | underscore_case (or whatever it's called), but instead just | runthemalltogetherit'stotallyfine? Why is the default for the | random number generator using the same seed every time you run | the program, and why does os.time() provide time not in | nanoseconds, or milliseconds, but solely in _whole_ seconds? Why | doesn 't the runtime complain if I pass in a completely non- | existent variable as an argument into a function? | | While the teaching has gone fine overall, the language actually | works against our purposes by making it harder for my son to | build a mental model of what's happening. The last point in the | previous paragraph, for example: it's much more confusing for a | newbie coder to have to deal with a 'sudden' nil value that they | weren't expecting, than to have a compiler or runtime just crash | and say "hey, I don't recognize this variable at this line | number". And yes, this isn't hypothetical, this actually happened | while I was teaching him. | | Same thing for the dynamic typing, and default global status of | variables. The lack of 'declaring' variable types, or even that a | thing is a variable at all, has meant that it's been more | confusing for him to identify what kind of value a variable is | holding, or even that an identifier is actually a variable at | all. That variables are by default global has made it harder to | teach him about passing in arguments -- he'll happily pass in | some variable as an argument, and then use _that_ variable name | within the function, rather than the argument name defined in the | function signature. These are the kinds of beginner-level | problems that you forget about as an experienced programmer, but | when you teach a kid, suddenly become very real. | | As I was using the language and teaching with it, I just couldn't | help but feel that more modern statically typed languages like | Swift or Kotlin would be flatly superior for the task of | instructing a young mind on the the most fundamental task of | beginner programming: getting them to build an accurate mental | model of "how this actually works, how does everything relate to | each other". You would get the enforced structure of older static | languages, but with more modern syntax and ease of use. To me, | it's hard to see what Lua would offer as an advantage, really. | But then again, I'm an Android developer, so maybe it's just my | own experience biasing me. | rstupek wrote: | A lot of those issues relate to the fact lua is dynamic and | typeless. It can for sure be a pita when you have a simple typo | in your variable and you don't find out until you run the app | and hit that code path. | TulliusCicero wrote: | Yes, I agree. Though I don't remember python behaving this | way, exactly, in terms of ignoring attempted use of non- | existent variables. | | > you don't find out until you run the app and hit that code | path. | | The real problem was that we didn't -- or rather, he didn't | -- even find out then, since it just looked like the variable | was somehow holding nil, instead of the variable not actually | existing. It looked like there was some other reason for the | variable accidentally being nil -- and when you're a total | beginner, it could be nearly anything. | | This setup is just...it's plainly more beginner-hostile than | a compiler/runtime simply telling the coder that there's a | problem, what the problem is, and what line it's at. So I | don't understand the people talking up Lua like it's great | for beginners. | | But yeah, I definitely dislike dynamically typed languages in | general. Having static typing with type inference ala Kotlin | just seems to be much better all around. | qayxc wrote: | > underscore_case (or whatever it's called) | | Snake case :) | | edit: https://en.wikipedia.org/wiki/Snake_case | fogleman wrote: | Dijkstra's well-known argument for zero-indexing. (Hint: it's not | about pointers in C) | | https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/E... | Jtsummers wrote: | That came up a few days ago, but in the context of Julia. I | wrote a long response at the time [0]. I find it interesting | that that's his title ("Why numbering should start at zero") | but it really only makes sense as an argument (that starting at | 0 is best) _if_ you accept that this is the proper notation for | ranges: a <= x < b | | _If_ you accept that, then the rest of his argument follows. | But if you use: a <= x <= b | | Then 1-based (where a = 1) indexing actually makes a lot of | sense as well, because the other reasons for selecting his | preferred range notation fall away. 1-based is only "weird" _if | you use his range notation_ because then you describe ranges | as: 1 <= x < N+1 | | Where N is the length of the range. But, if you use the second | form: 1 <= x <= N | | Which reads fairly well. | | [0] https://news.ycombinator.com/item?id=25723676 | 1vuio0pswjnm7 wrote: | People employed as programmers who are vocal in mailing lists, | forums, blogs, etc. can have some very warped views on | programming. Curiously, their statements often take a didactic | tone. It seems they want to tell others what to do and what not | to do. Sadly, these are not the folks who anyone should be | attempting to "learn" from. They are antithetical to curiousity. | Nice to hear something from someone who is not working as a | programmer. This is a much clearer perspective, IMO. At the very | least, regardless of anyone's opinion, it gives us a more | balanced perspective. | fwsgonzo wrote: | I have always understood the reason why Lua keeps getting | embedded into games and game engines is because it's a language | that you can reasonably hope non-technical people to be able to | contribute a little bit from. | | I know that from experience myself. I've moved on from Lua to | using tiny virtual machines that run RISC-V instead, and so I | choose to use Nim inside the VMs in the hopes that non- | technical people will find that easy to grok, somehow. I don't | have any anecdata to report yet because it's still early in the | project. But, that's the only thing I consider when choosing | the language. | TulliusCicero wrote: | I've had the opposite experience. Teaching my 9 year old son | Lua has been kind of painful, in large part because of | language decisions that make learning things harder for | beginners. | | For example, did you know that if you pass in a variable to a | function, when that variable doesn't actually exist, Lua | won't complain? I don't just mean that there's no compiler, | but even the runtime is fine with it. It'll just silently | assign the argument value to be nil. | | This resulted in my son being very confused, after having a | typo in the variable name he was using there. Why is the | value nil? He was sure he gave it a value earlier, before | passing it into the function (and he was correct, to an | extent). | | I have a laundry list of complaints about the language, | things that make it harder to teach beginners. Sure, there's | less 'setup' than, say, Java, and that's nice. And the | 1-indexing is fine, really. | | But there's other language decisions that are just _weird_ , | man. Why would you make this 'table' structure so flexible | and important, and then completely neglect to provide a | built-in function create copies of said table? How is that | non-programmer-friendly? How is providing no ++ or += | increment operators better for beginners? | striking wrote: | I gave you an upvote because I think you don't deserve to | go negative just for raising some of these concerns. Still, | I'm going to examine some of them. | | With regards to variables, the best way to hack around this | issue is to 1) always use `local` when declaring a variable | and 2) set the `_G` metatable to never allow the creation | of keys, which prevents accidentally using globals like | you've inadvertently discovered is the default behavior. | This is this way because it is I guess simpler than | teaching someone how declarations work, but it obviously | leads to a pretty immediately bad situation for anyone who | wants to do more programming than setting a global | constant. It harkens back from when Lua was basically a | TCL-like. | | Copying a table is generally unnecessary, if you never | mutate the table to be cloned. Just set the __index | property of a new table to a reference to the table to be | cloned. Ta-da, you have inherited the previous table. Not | giving you an immediate, easy way to do this forces you to | come to terms with copying not always being the right | solution. It's not great, and the language offers no | pointers to those who want to get a thing done, but it | isn't the worst choice. | | Not providing increment operators is a design choice, one | that simplifies the metatabling for operators. Only having | one case for addition, and not having to worry about | increment / incremental assignment, means people creating | metatables that override operators have a good experience. | This is one of those times where power users are given the | advantage at the cost of the less experienced, and I share | your implied concern in feeling the inconsistencies in who | is favored by which language features. | diego_moita wrote: | > Lua is small enough that newbie developers can understand its | internals well and keep it in their mind. | | This is, by far, Lua's best "feature". If you know programming | you can learn 90% of Lua in 15 minutes (metatables and the C | stack interface takes more time). | | For a language meant to be used by non-programmers this is more | than precious, it is essential. | | Edit: my favourite Lua-enabled tools: | | 1) Hammerspoon, an automation tool for OS-X (like Windows' | AutoHotkey) https://www.hammerspoon.org/ | | 2) Openresty, Nginx turbo-charged in Lua: | https://openresty.org/en/ | | 3) Wireshark, a powerful network traffic analyzer: | https://www.wireshark.org/ | | Many others at: https://github.com/LewisJEllis/awesome-lua | | PS: on Windows I highly recommend the ZeroBrane Studio IDE. It is | really fantastic. | lxe wrote: | Lua static binary can be made to be less than ~150k, while | providing very advanced high level dynamic language features | you'd expect from JavaScript or PHP. | | I used it to build a admin UI for an embedded device without an | MMU. The only other alternative available was C/C++, which slowed | the iteration cycle significantly. | | Yeah it does things in a strange way, but when I used it, those | quirks are vastly overshadowed by its benefits. | jcims wrote: | Did you compile to bytecode on or off the device? | | I'm thinking about trying to add Lua support to a small motor | controller to provide some more advanced capability inside the | control loop. But I don't actually have any experience doing | this, and I can't even decide if I want to try to compile the | bytecode on the device or do that off the device and push the | blob to the device. | | It's pretty capable microcontroller, STM32G4. | 1vuio0pswjnm7 wrote: | nmap's "nse" scripts are perhaps an interesting example of lua's | utility | | https://nmap.org/nsedoc/scripts/ | | and if by chance you have nmap installed: | | /usr/share/nmap/nselib/ | aeturnum wrote: | My first real job after school was working on Lua (5.1a mostly) | in an embedded context. It was much faster than iterating on the | QT C++ application that the Lua was embedded in. It would, | eventually, even allow us to do custom targeted push updates to | our software (in 2009). | | So I love Lua. I appreciate its speed and its flexibility. I | think of it as Javascript's easy to use cousin. Straightforward | to write and debug - you control the entire environment. | | I also think this idea is deeply silly: | | >People who want batteries want a ready-made powertool full of | opinions. They are not looking towards Lua in the context that | Lua wants to exist. | | I would have loved ready-made powertools! I wouldn't include all | the tools in _my_ toolkit (and we already added some by building | our own Lua with a few patches), but it sure would have saved me | time writing them (and writing them badly as I was just out of | school). I don 't think a complicated, robust library would hurt | Lua's mission and I'm sad to see this attitude in the community. | I understand that Lua may be too small to support a "big" set of | official libraries, but I think the idea that offering fewer | options is better than more options is wrong. ___________________________________________________________________ (page generated 2021-01-15 23:00 UTC)