lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Hash: SHA1

John Hind wrote:
> I keep coming across the "global by default is bad, local by default is
> worse" statement, but I've never seen a convincing justification for it.
> There's lots of code examples that people claim "don't do what you'd
> expect", but mostly they do exactly what I'd expect!

Okay, I'll bite... but I'll probably regret it!

Examine the following code:

n = 1
function foo()
  return function()
    return function()
      if bingy then
      print(n + 1)

At first glance, this seems perfectly reasonable. But now let's apply
local-by-default. To make that work, the inner function needs to declare
n with a 'global n'. Except...  that if clause defines a scope level,
too. Do you need to declare n inside the then statement as well?
Obviously not, because that would be silly, but in order to make that
work you now have to distinguish between scopes that inherit locals (the
if...then...end one) and scopes that don't (the function()...end one).

But now it still won't work, because that inner function is embedded
inside another function. Does the 'global n' import the symbol from the
outermost scope, or from the next enclosing one? If the former, then
we've introduced a third type of scope, the globals-defining scope at
the top level; and we introduce inconsistent behaviour because simply
wrapping the entire program in another function will cause it not to
work, because n is no longer defined in a globals-defining scope. And if
it's the latter, then we end up having to have a chain of 'global'
statements importing n all the way up the set of scopes so we can access
it in that innermost closure.

But it gets worse! That 'print()' statement. 'print' is a global, which
means that we need to import it... If we are using the logically
consistent global-inherits-from-enclosing-scope rule, then we need to
import it in every function that defines a function that uses it; but if
we use the global-inherits-from-outermost-scope rule, then we still need
to explictly declare it in every closure that might want to access it.

I simply cannot see any clean way around this. As soon as you start
using locals-by-default you end up in a horrible maze of special cases
and inconsistencies. We've already had to define three new types of
scope and have a choice between two perfectly logical but practically
troublesome interpretations of one of the statements. And we haven't
even started on the philosphical morass that is...

  i = i + 1

- --
┌─── ───── ─────
│ "Wizards get cranky, / Dark days dawn, / Riders smell manky, / The
│ road goes on. / Omens are lowering, / Elves go West; / The Shire needs
│ scouring, / You may as well quest." - John M. Ford
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla -