[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: What's wrong with this Lua code?
- From: Sean Conner <sean@...>
- Date: Fri, 16 Jun 2017 18:21:05 -0400
It was thus said that the Great Jonathan Goble once stated:
> On Fri, Jun 16, 2017 at 3:45 PM Soni L. <fakedme@gmail.com> wrote:
>
> > I have this Lua code:
> >
> > local string = "" print(string.format("%X", 16777216))
> >
> > And it works perfectly, but I was told it's wrong? What's wrong with it?
> > Why shouldn't I do this?
> >
>
> Let's break it down:
>
> > local string = ""
>
> The variable `string` is now an empty string and, in this scope, no longer
> references the `string` standard library.
>
> > print(string.format("%X", 16777216))
>
> Here, Lua first looks up `string.format`. While `string` no longer refers
> to the string standard library, it is an actual string, and strings (since
> Lua 5.1) have a metatable with an __index metamethod pointing to the actual
> string library (which isn't changed by your local `string` assignment, nor
> would an assignment to the global `string` affect it). So the lookup of
> `string.format` produces, via metamethod, the string standard library
> function `format`. From there, you can call it with whatever arguments you
> want.
>
> So why is it a bad idea? One, because indexing through a metamethod is
> slower than directly indexing the actual `string` table, and two, because
> shadowing a built-in global (whether with a global or local assignment) is
> usually a code smell (in any language) and generally shouldn't be done
> without a very good reason.
You have to shadow the built-in globals for modules written in Lua 5.1
because the global environment goes away when you call module(). I still
do that in Lua 5.3 because I attempt to maintain compatability with Lua 5.1:
local _VERSION = _VERSION
local math = require "math"
local string = require "string"
local io = require "io"
local pairs = pairs
local tostring = tostring
local type = type
local print = print
local pcall = pcall
local getmetatable = getmetatable
if _VERSION == "Lua 5.1" then
module("org.conman.table")
else
_ENV = {} -- luacheck: ignore
end
function dump(name,value)
-- ...
end
if _VERSION >= "Lua 5.2" then
return _ENV -- luacheck: ignore
end
Yes, I require() the base modules because that signals intent. If I could
require() global functions like type() or pcall(), I would do that as well
(if I could do that, a side effect is that the only global in scope would be
require()).
-spc