Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

It's definitely surprising that globals default to nil, but it makes a little bit more sense in the embedding context where the global environment is controlled by the C code. Overall there are a lot of decisions (like the lack of a function to copy tables) that are based on the assumption that any given Lua code was written for and executing in an environment created by a programmer who is going to roll their own standard library, make any tweaks to the syntax they like, etc. And I agree that for that reason it's not in itself a great language for learners, but that's not exactly the same as being a great language for non-programmers.


> It's definitely surprising that globals default to nil, [..]

If you've worked a bit with Lua, it's actually pretty reasonably and consistent: Everything is a table and accessing unset variables is accessing the table (named _G) holding all global variables. So

  print(a)
assuming a isn't a local variable, is essentially the same as

  print(_G['a']) -- or print(_G.a)
As accessing unset keys within a table returns nil, doing so for globals makes it consistent. Also _G._G == _G :-)


Since Lua 5.2 non-locals are loaded from the table/object _ENV. Every lexical context has either an implicit _ENV, or an explicit _ENV (e.g. nearest `local _ENV = ...`). The default value for implicit _ENV is the global table (i.e. _G, but not literally _G; it's initialized as if from lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD)). See https://www.lua.org/manual/5.4/manual.html#2.2

Lua 5.1 had something similar, but the implicit environment was per-function.

A common pattern in Lua is to change _ENV to an empty table with a __newindex meta-method that writes-through to the real global environment, and an __index meta-method that throws an error if the key (i.e. global symbol) doesn't exist. You can fancy and have an __index meta-method that that throws an error string with suggestions for a possibly misspelled symbol, similar to clang or GCC compiler diagnostics.


At this point, I've worked 'a bit' with Lua, in addition to plenty of other coding experience, and it's still surprising to me.

> Everything is a table and accessing unset variables is accessing the table (named _G) holding all global variables.

Before you said this, I had no idea about that. Because it's not like the tutorials are talking about the underlying implementation for this stuff, just like how Java tutorials don't usually go deep in explaining how bytecode works, or how the JVM can be used to interoperate with other languages.


Never mind Lua tutorials. Just read the manual, https://www.lua.org/manual/5.4/, and maybe the canonical Programming in Lua book, https://www.lua.org/pil/

Lua is an incredibly simple and elegant language. All the myths and bike-shedding on Stack Overflow and elsewhere can only lead you astray. For exceptional situations, use the mailing-list. The authors and almost all experts are on the mailing-list and will be quick to correct errors. (Everybody is wrong sometimes, even the authors! But you need enough experts in one place to be paying attention, and the only such place is the mailing-list.)

Another thing to keep in mind is that Lua maintains strict feature symmetry between what's possible in Lua code, and what's possible from the Lua C API. This is important to understand if you want to have a good mental model of the language and why it's designed the way it is. If you're not a C programmer or haven't heavily used the Lua C API, many of Lua's choices may seem arbitrary, especially coming from other languages where their C ABI and FFI interfaces are mostly an afterthought or don't otherwise constrain the in-language semantics. Most "better than Lua" projects are written by people without a sufficient appreciation for this aspect of Lua's design.


So just to be clear here, the things you're recommending a nine year old to do are: ignore tutorials in favor of reading directly from the language reference manual, and keeping in mind the language's C API parity.

> This is important to understand if you want to have a good mental model of the language and why it's designed the way it is.

I want to have a good mental model of the code I write, and how that works, not the underlying language mechanisms themselves.

I've been picking up Kotlin, and I hardly know anything of how it works under the hood, other than whatever it 'inherits' from being a JVM language, and so far it's been totally fine. Why should I need to care about how the sausage is made?


> the things you're recommending a nine year old to do are

Are you the nine-year-old? I was responding to a criticism you made regarding your understanding. Are online tutorials for children learning their first programming language supposed to explain the rationale behind the language design? If you want the latter don't use children's tutorials, or in the case of Lua, any tutorials, because the official material is at least as easy to understand, and infinitely more reliable and accurate.


Sure, which is why I said "surprising" and not "inconsistent" or "weird". New Lua devs are likely to have to debug an issue caused by typing "ponits" instead of "points" well before they get to the point that they learn about the global table.


> And I agree that for that reason it's not in itself a great language for learners, but that's not exactly the same as being a great language for non-programmers.

I'm definitely critiquing it from a standpoint of how we've been using it: as a scripting language for making games. We're doing it with this Undertale thing, and there's a good chance he'll use it with Roblox, because the kid loves Roblox, and Lua is used there for scripting as well.

And in that context, it's for non-programmers in a sense, sure, but it's also for people learning to program. Those aren't conflicting descriptions, right? Because initially you can call them 'non-programmers', but at a certain level of complexity, calling them non-programmers doesn't even make sense anymore (and the Roblox custom games I've seen him play, they seem plenty complex to me).


> It's definitely surprising that globals default to nil

It makes a lot of sense once you realise that assigning to a "global variable X" (which is equivalent to _G[X]) and then assign nil, is exactly the same as never assigning at all




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: