In Lua, you can say `a, b = foo(), bar()`. This can have all sorts of unintuitive consequences if there is an addition after, and one of the function calls mutates something the other one depends on. you can also have `a, b = foo()`, since it can return two values.
So Luau (the Roblox dialect) limits += statements to one lvalue, which is unsatisfying but at least a reasonable decision. I think it's worth having, but I get why Lua doesn't include that: they're quite committed to a minimal set of abstractions which compose cleanly.
There are similar answers for all of your questions but, more to the point: Lua doesn't try to be a teaching language. It's minimal, easy enough for a skilled programmer to acquire, and remarkably powerful for how tiny the whole thing is. But to really get somewhere with it, you want to grasp the entire language, and that works against it being a good first language.
That said, it isn't a bad first language either. It does demand more of you as a teacher: we can't expect a nine-year-old to copy-paste a table clone function out of the Lua wiki, or find strict mode in penlight, but it sounds like you're capable of both of those things.
Neither of those are hypotheticals, they're hurdles I cleared years ago and have to consciously remind myself exist in a clean install of the language!
> 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.
And static typing is hard to make work when your codebase is made up of a lot of independent snippets of code which run in an environment completely determined by an outside program. You'd need something akin to TypeScript's external type definition files.
function no_globals()
setmetatable(_G, {
__newindex = function(t, k, v)
return error("attempt to set global '"..tostring(k))
end,
__index = function(t, k)
return error("attempt to reference missing global '"..tostring(k))
end,
})
end
can help catch assignment and usage of undefined (e.g. by not using 'local') variables. The downside is that this then also applies to function definitions. So be prepared to write 'local function xyz()'.My complaint is that, if the language is supposed to be good for beginners, the workarounds should be unnecessary, since beginners are unlikely to a) be able to find proper workarounds, or b) even be aware that there's a problem that a workaround would be needed to solve.
My son has no idea that invoking an un-initialized global variable immediately brings it into being with 'nil' is weird behavior for a language. If a less experienced programmer was the one helping him learn, they might not realize it either.
But I want to stand up for this, in particular. Because in most languages, environments are magic: they're an exceptional thing that you work with in a special way, you're not expected to understand them, just use them.
In Lua, an environment is... just a table! You can set an environment, read from it directly, assign it a metatable, and so on.
So this is great for a beginner, once he gets past the hurdle. Just like `table.field` returns `nil` if there's no field field, `field` itself returns nil if there's no `_G.field`. Because _G.field and field itself are the same thing.
Is it? Because that still seems very error prone to me. You're not gonna suddenly stop making typos just because you understand that there's an invisible global table around all the time.
But hey, maybe it's super awesome later on, though I'm having trouble imagining scenarios where this behavior is all that useful over what most other languages do.
Snake case :)
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.