Discussion:
Say No to global-by-default
Egor Skriptunoff
2018-07-04 05:26:18 UTC
Permalink
Hi!

Let me start (n+1)-th thread about "global by default" feature of Lua.

My suggestion is to replace "global by default" approach with "nothing by
default" by introducing special syntax for accessing global variables:

$print("Hello world") -- ok
print("Hello world") -- syntax error: referencing undeclared variable
"print"
_G.print("Hello world") -- syntax error: referencing undeclared variable
"_G"

"$" is not a part of an identifier.
"$" is a lexem (for example, there could be a space between "$" and global
variable name).
"$" is absolutely the same as "_ENV." but is more comfortable to use.

Why do we need this?

1)
"$globalvar" notation introduces two separate namespaces: one for globals
and one for locals/upvalues.
As a result of this separation, most of variable name typos will be
detected at compile time.
Although global name typos will not be detected ($math.sin -> $moth.sin),
the most of identifiers in properly-written Lua programs are locals.
Currently, writing Lua programs without "global-nil-alarmer" (such as
"strict.lua") is practically impossible (because typos in local variable
names are silently converted to globals).

2)
"$print" contains more symbols than "print", and you have to press SHIFT on
your keyboard to type "$", but this is not a drawback.
Instead, there is a point in it: users would have to pay attention to slow
global access.
More finger moves = more CPU time to access.
So, we are adding "ergonomical motivation" to cache globals in Lua programs
:-)

3)
Polluting of global namespace is already discouraged in Lua, so introducing
"$" prefix for globals is the next step in that direction.
It is a polite way to say: "use globals only when they are really needed".

4)
The "$globalvar" notation will solve problem with globals occasionally
shadowed out by locals or upvalues:

local function sort_desc(table)
table.sort(table, function(a, b) return a>b end) -- very popular
newcomers' mistake
end

5)
The "$globalvar" notation will make the difference between
"monkey-patch-friendly code" and "monkey-patch-unfriendly code" more easy
to see.


BTW, "_ENV" could be removed from Lua as "$" could do the same (with some
modifications in the parser to interpret "$" either as "_ENV." or as
"_ENV"):

$print() -- instead of print()
$.print() -- instead of print()
local env = $ -- instead of local env = _ENV
$[key] = value -- instead of _ENV[key] = value
function sndbx($) -- instead of function sndbx(_ENV)


What are your thoughts on this?

-- Egor
Steven K.
2018-07-04 05:39:25 UTC
Permalink
Hello,

"global-by-default" is evil, no more to say.
I'm using Lua mostly embedded, just some globals to work and life with the
environment. At this point if view, where are the benefits for me?

Greetings.
Post by Egor Skriptunoff
Hi!
Let me start (n+1)-th thread about "global by default" feature of Lua.
My suggestion is to replace "global by default" approach with "nothing by
$print("Hello world") -- ok
print("Hello world") -- syntax error: referencing undeclared variable
"print"
_G.print("Hello world") -- syntax error: referencing undeclared variable
"_G"
"$" is not a part of an identifier.
"$" is a lexem (for example, there could be a space between "$" and global
variable name).
"$" is absolutely the same as "_ENV." but is more comfortable to use.
Why do we need this?
1)
"$globalvar" notation introduces two separate namespaces: one for globals
and one for locals/upvalues.
As a result of this separation, most of variable name typos will be
detected at compile time.
Although global name typos will not be detected ($math.sin -> $moth.sin),
the most of identifiers in properly-written Lua programs are locals.
Currently, writing Lua programs without "global-nil-alarmer" (such as
"strict.lua") is practically impossible (because typos in local variable
names are silently converted to globals).
2)
"$print" contains more symbols than "print", and you have to press SHIFT
on your keyboard to type "$", but this is not a drawback.
Instead, there is a point in it: users would have to pay attention to slow
global access.
More finger moves = more CPU time to access.
So, we are adding "ergonomical motivation" to cache globals in Lua
programs :-)
3)
Polluting of global namespace is already discouraged in Lua, so
introducing "$" prefix for globals is the next step in that direction.
It is a polite way to say: "use globals only when they are really needed".
4)
The "$globalvar" notation will solve problem with globals occasionally
local function sort_desc(table)
table.sort(table, function(a, b) return a>b end) -- very popular
newcomers' mistake
end
5)
The "$globalvar" notation will make the difference between
"monkey-patch-friendly code" and "monkey-patch-unfriendly code" more easy
to see.
BTW, "_ENV" could be removed from Lua as "$" could do the same (with some
modifications in the parser to interpret "$" either as "_ENV." or as
$print() -- instead of print()
$.print() -- instead of print()
local env = $ -- instead of local env = _ENV
$[key] = value -- instead of _ENV[key] = value
function sndbx($) -- instead of function sndbx(_ENV)
What are your thoughts on this?
-- Egor
Egor Skriptunoff
2018-07-04 06:04:59 UTC
Permalink
Post by Steven K.
"global-by-default" is evil, no more to say.
I'm using Lua mostly embedded, just some globals to work and life with the
environment. At this point if view, where are the benefits for me?
$Do $you $want $to $say $that $you $don't $use $local $variables $in $your
$scripts?
Steven K.
2018-07-04 06:36:35 UTC
Permalink
In my scripts of corse, but not in the application where Lua is used as
embedded scripting language. in this case the mass of scripts comming from
other "users".
Post by Egor Skriptunoff
Post by Steven K.
"global-by-default" is evil, no more to say.
I'm using Lua mostly embedded, just some globals to work and life with
the environment. At this point if view, where are the benefits for me?
$Do $you $want $to $say $that $you $don't $use $local $variables $in $your
$scripts?
Egor Skriptunoff
2018-07-04 21:21:59 UTC
Permalink
Lua is used as embedded scripting language.
Post by Steven K.
I'm using Lua mostly embedded, just some globals to work and life with
Post by Steven K.
the environment. At this point if view, where are the benefits for me?
You are correct.
Indeed, the suggested new rule "all globals must start with $" wouldn't
bring benefit to embedded/config/DSL scripts where local variables are used
rarely or not used at all.
Lua must be able to successfully compile scripts using the old rule "allow
$-less globals" (otherwise "global-only-variables users" would be unhappy).

To make all Lua users happy, "load()"/"lua_load()" should automatically
select most suitable rule for a script being compiled:
- If at least one identifier starting with "$" was found in the script then
this script must be compiled with new rule "all globals must start with $".
- If no such identifiers were found in the script, then this script must be
compiled with old rule "allow $-less globals".
This way, 100% backward-compatibility would be achieved.

To implement rule auto-selection described above, there would be no need
for two-pass compiler.
When first $-less global name is encountered, we create an error message (a
string) and save this string without raising an error.
When first "$" lexem is encountered, we are raising error with saved string
as error message.

So, both groups of Lua users (those who love global-by-default and those
who hate it) would obtain what they want.
Gregg Reynolds
2018-07-04 22:02:05 UTC
Permalink
Post by Egor Skriptunoff
Lua is used as embedded scripting language.
Post by Steven K.
I'm using Lua mostly embedded, just some globals to work and life with
Post by Steven K.
the environment. At this point if view, where are the benefits for me?
You are correct.
Indeed, the suggested new rule "all globals must start with $" wouldn't
bring benefit to embedded/config/DSL scripts where local variables are used
rarely or not used at all.
Lua must be able to successfully compile scripts using the old rule "allow
$-less globals" (otherwise "global-only-variables users" would be unhappy).
To make all Lua users happy, "load()"/"lua_load()" should automatically
- If at least one identifier starting with "$" was found in the script
then this script must be compiled with new rule "all globals must start
with $".
A recipe for disaster, imho. Again, you're defining a different language.
Let's call it lua$. Now whenever I look at Lua code the first thing I have
to do is figger out if it is genuine Lua, or lua$. No, thanks.


- If no such identifiers were found in the script, then this script must be
Post by Egor Skriptunoff
compiled with old rule "allow $-less globals".
This way, 100% backward-compatibility would be achieved.
To implement rule auto-selection described above, there would be no need
for two-pass compiler.
When first $-less global name is encountered, we create an error message
(a string) and save this string without raising an error.
When first "$" lexem is encountered, we are raising error with saved
string as error message.
So, both groups of Lua users (those who love global-by-default and those
who hate it) would obtain what they want.
Sean Conner
2018-07-04 07:06:09 UTC
Permalink
Post by Egor Skriptunoff
Post by Steven K.
"global-by-default" is evil, no more to say.
I'm using Lua mostly embedded, just some globals to work and life with the
environment. At this point if view, where are the benefits for me?
$Do $you $want $to $say $that $you $don't $use $local $variables $in $your
$scripts?
If I want to program in Perl, I know where to find it.

And yes, for one off scripts, I don't really bother with declaring
variables as local.

-spc
Gregg Reynolds
2018-07-04 20:08:36 UTC
Permalink
Post by Sean Conner
Post by Egor Skriptunoff
Post by Steven K.
"global-by-default" is evil, no more to say.
I'm using Lua mostly embedded, just some globals to work and life with
the
Post by Egor Skriptunoff
Post by Steven K.
environment. At this point if view, where are the benefits for me?
$Do $you $want $to $say $that $you $don't $use $local $variables $in
$your
Post by Egor Skriptunoff
$scripts?
If I want to program in Perl, I know where to find it.
+1
Post by Sean Conner
And yes, for one off scripts, I don't really bother with declaring
variables as local.
-spc
Dirk Laurie
2018-07-04 10:25:05 UTC
Permalink
Post by Steven K.
"global-by-default" is evil, no more to say.
I am nevertheless going to say something.
Post by Steven K.
I'm using Lua mostly embedded, just some globals to work and life with the environment. At this point if view, where are the benefits for me?
Global in Lua does not mean global in the sense other languages use
it. It means "if the block structure does not resolve the name, look
for it in _ENV."

It is a highly useful construct. For example:

local function myfunc(_ENV)
-- equivalent of Pascal's 'with' statement
x = 1
y = 2
end

myfunc(t) -- does t.x = 1, t.y = 2

If you really hate global-by-default, you can disable it easily.

local next, io, print = next, io, print
-- etc: first cache all the globals you need
local _ENV = setmetatable({},{__index=error, __newindex=error})

You now need to say rawset(_ENV,key,value) to define a global
variable, but once you have done it, normal indexing works as usual.

If you really want it to look nice,

local global = function(key)
rawset(_ENV,key,value) = '[exists]'
end

allows the syntax global'var' to define a new global.
Egor Skriptunoff
2018-07-04 20:52:49 UTC
Permalink
local _G = _G; local _ENV = nil
and then use e.g. `_G.print
local next, io, print = next, io, print
-- etc: first cache all the globals you need
local _ENV = setmetatable({},{__index=error, __newindex=error})
These are two more "yet another run-time alarmers".
They are not equivalent to my suggestion.

Any "runtime-alarmer" is unable to find all local variable name typos (for
example, inside currently inactive "if" branch).
I suggested to introduce separate namespace for locals/upvalues (variable
names without "$") for 100% checking for local/upvalue name typos at
compile-time (not run-time).
Nevertheless, a "runtime-alarmer" would still be needed for detecting
global variable name typos as run-time.


If you really hate global-by-default, you can disable it easily.
I do not hate globals :-)
I'm trying to solve the problem "the compiler silently ignores all variable
name typos".
It's the expectation of many programmers that a compiler should check for
misspelled identifiers and warn the user at compile time.
And the global-by-default feature is the only thing in Lua that prevents
this to happen.

All existing solutions are actually run-time checkers, they are unable to
solve the problem.
And simultaneously I want to solve another problem "globals are
accidentally shaded out by locals with the same name".
"$" solves both these problems.
Gregg Reynolds
2018-07-04 21:22:18 UTC
Permalink
Post by Egor Skriptunoff
I do not hate globals :-)
I'm trying to solve the problem "the compiler silently ignores all
variable name typos".
It's the expectation of many programmers that a compiler should check for
misspelled identifiers and warn the user at compile time.
Now I'm completely confused. I never heard of a compiler that could do
that. What does "misspelled identifier" mean to a compiler? I must be
missing your point, sorry.

And the global-by-default feature is the only thing in Lua that prevents
Post by Egor Skriptunoff
this to happen.
All existing solutions are actually run-time checkers, they are unable to
solve the problem.
And simultaneously I want to solve another problem "globals are
accidentally shaded out by locals with the same name".
"$" solves both these problems.
Sean Conner
2018-07-04 21:32:52 UTC
Permalink
Post by Gregg Reynolds
Post by Egor Skriptunoff
I do not hate globals :-)
I'm trying to solve the problem "the compiler silently ignores all
variable name typos".
It's the expectation of many programmers that a compiler should check for
misspelled identifiers and warn the user at compile time.
Now I'm completely confused. I never heard of a compiler that could do
that. What does "misspelled identifier" mean to a compiler? I must be
missing your point, sorry.
[spc]lucy:/tmp>more a.c

int foo(int bar)
{
int baz = 5;
return baa + bar;
}
[spc]lucy:/tmp>gcc a.c
a.c: In function oo':
a.c:5: error: `baa' undeclared (first use in this function)
a.c:5: error: (Each undeclared identifier is reported only once
a.c:5: error: for each function it appears in.)

But in C, you have to declare every variable upfront. In Lua:

function foo(bar)
local baz = 5
return baa + bar
end

'baa' is treated as a global variable who's value is nil (and thus in *this*
case you get an error, but this won't happen in all cases).

-spc
Gregg Reynolds
2018-07-04 21:36:02 UTC
Permalink
Ok, but what does that have to do with spelling?
Post by Sean Conner
On Wed, Jul 4, 2018, 3:53 PM Egor Skriptunoff <
Post by Egor Skriptunoff
I do not hate globals :-)
I'm trying to solve the problem "the compiler silently ignores all
variable name typos".
It's the expectation of many programmers that a compiler should check
for
Post by Egor Skriptunoff
misspelled identifiers and warn the user at compile time.
Now I'm completely confused. I never heard of a compiler that could do
that. What does "misspelled identifier" mean to a compiler? I must be
missing your point, sorry.
[spc]lucy:/tmp>more a.c
int foo(int bar)
{
int baz = 5;
return baa + bar;
}
[spc]lucy:/tmp>gcc a.c
a.c:5: error: `baa' undeclared (first use in this function)
a.c:5: error: (Each undeclared identifier is reported only once
a.c:5: error: for each function it appears in.)
function foo(bar)
local baz = 5
return baa + bar
end
'baa' is treated as a global variable who's value is nil (and thus in *this*
case you get an error, but this won't happen in all cases).
-spc
Sean Conner
2018-07-04 21:41:47 UTC
Permalink
Post by Gregg Reynolds
Ok, but what does that have to do with spelling?
I mispelled 'baz' as 'baa'.

-spc
Post by Gregg Reynolds
Post by Sean Conner
On Wed, Jul 4, 2018, 3:53 PM Egor Skriptunoff <
Post by Egor Skriptunoff
I do not hate globals :-)
I'm trying to solve the problem "the compiler silently ignores all
variable name typos".
It's the expectation of many programmers that a compiler should check
for
Post by Egor Skriptunoff
misspelled identifiers and warn the user at compile time.
Now I'm completely confused. I never heard of a compiler that could do
that. What does "misspelled identifier" mean to a compiler? I must be
missing your point, sorry.
[spc]lucy:/tmp>more a.c
int foo(int bar)
{
int baz = 5;
return baa + bar;
}
[spc]lucy:/tmp>gcc a.c
a.c:5: error: `baa' undeclared (first use in this function)
a.c:5: error: (Each undeclared identifier is reported only once
a.c:5: error: for each function it appears in.)
function foo(bar)
local baz = 5
return baa + bar
end
'baa' is treated as a global variable who's value is nil (and thus in *this*
case you get an error, but this won't happen in all cases).
-spc
Gregg Reynolds
2018-07-04 21:48:04 UTC
Permalink
Post by Sean Conner
Post by Gregg Reynolds
Ok, but what does that have to do with spelling?
I mispelled 'baz' as 'baa'
Haha! But that screws up your example.
-spc
Post by Sean Conner
Post by Gregg Reynolds
Post by Sean Conner
On Wed, Jul 4, 2018, 3:53 PM Egor Skriptunoff <
Post by Egor Skriptunoff
I do not hate globals :-)
I'm trying to solve the problem "the compiler silently ignores all
variable name typos".
It's the expectation of many programmers that a compiler should
check
Post by Gregg Reynolds
Post by Sean Conner
for
Post by Egor Skriptunoff
misspelled identifiers and warn the user at compile time.
Now I'm completely confused. I never heard of a compiler that could
do
Post by Gregg Reynolds
Post by Sean Conner
that. What does "misspelled identifier" mean to a compiler? I must be
missing your point, sorry.
[spc]lucy:/tmp>more a.c
int foo(int bar)
{
int baz = 5;
return baa + bar;
}
[spc]lucy:/tmp>gcc a.c
a.c:5: error: `baa' undeclared (first use in this function)
a.c:5: error: (Each undeclared identifier is reported only once
a.c:5: error: for each function it appears in.)
function foo(bar)
local baz = 5
return baa + bar
end
'baa' is treated as a global variable who's value is nil (and thus in *this*
case you get an error, but this won't happen in all cases).
-spc
Sean Conner
2018-07-04 22:24:25 UTC
Permalink
Post by Gregg Reynolds
Post by Sean Conner
Post by Gregg Reynolds
Ok, but what does that have to do with spelling?
I mispelled 'baz' as 'baa'
Haha! But that screws up your example.
Okay, fine:

int foo()
{
int baz;
// lots of code here
return baa;
}

and

function foo()
local baz
-- lots of code here
return baa
end

Better? C will compilain about 'baa' not being defined, while Lua will
silently treat 'baa' as a global value and return nil.

-spc (I still get bit by this in Lua, but luacheck helps here)
Gregg Reynolds
2018-07-04 22:28:23 UTC
Permalink
Post by Sean Conner
Post by Gregg Reynolds
Post by Sean Conner
Post by Gregg Reynolds
Ok, but what does that have to do with spelling?
I mispelled 'baz' as 'baa'
Haha! But that screws up your example.
int foo()
{
int baz;
// lots of code here
return baa;
}
and
function foo()
local baz
-- lots of code here
return baa
end
Better? C will compilain about 'baa' not being defined, while Lua will
silently treat 'baa' as a global value and return nil.
Yep. But it has nothing to do with "spelling". Compilers are stupid, and
they certainly do not have spelling rules.
Post by Sean Conner
-spc (I still get bit by this in Lua, but luacheck helps here)
Sean Conner
2018-07-04 22:57:55 UTC
Permalink
Post by Gregg Reynolds
Post by Sean Conner
Post by Gregg Reynolds
Post by Sean Conner
Post by Gregg Reynolds
Ok, but what does that have to do with spelling?
I mispelled 'baz' as 'baa'
Haha! But that screws up your example.
int foo()
{
int baz;
// lots of code here
return baa;
}
and
function foo()
local baz
-- lots of code here
return baa
end
Better? C will compilain about 'baa' not being defined, while Lua will
silently treat 'baa' as a global value and return nil.
Yep. But it has nothing to do with "spelling". Compilers are stupid, and
they certainly do not have spelling rules.
Seriously? You're hung up on the work "misspelling"? As in, a compiler
won't flag 'mispelling' because it's misspelled? The Oxford English
Dictionary has the following for 'misspell':

v. trans. To spell incorrectly

vbl. sp. A bad spelling; false orthography

And even Merriam-Webster lists "to spell (a word or name) incorrectly". So
Post by Gregg Reynolds
It's the expectation of many programmers that a compiler should check for
misspelled identifiers and warn the user at compile time.
is, to me, be correct---'baa' is false orthography [1] of "baz" (per
Oxford); I spelled 'baz' (a word or name and in this case, it's a name)
incorrectly (per Merriam-Webster). I think you are interpreting the term
'misspelling' too narrowly (I do not know if English is your first language
or not) or are trolling.

-spc (I'm not even sure if English is Egor's first language or not,
so I'm willing to give both of you the benefit of the doubt here)

[1] "Orthography" releates to spelling:

Correct or proper spelling; spelling accoring to accepted
usage; the way in which words are conventionally written.
(By extension) Any mode or system of spelling.
-- Oxford English Dictionary

Here, I would aplly "any more or system of spelling" to program
identifiers. Certainly, the compiler keeps track of identifiers,
and in some cases (like C) deviations to the spelling of an
identifier can be found.
Gregg Reynolds
2018-07-05 18:17:33 UTC
Permalink
Post by Sean Conner
Post by Egor Skriptunoff
Post by Sean Conner
Post by Gregg Reynolds
Ok, but what does that have to do with spelling?
I mispelled 'baz' as 'baa'
Seriously? You're hung up on the work "misspelling"? As in, a compiler
won't flag 'mispelling' because it's misspelled? The Oxford English
v. trans. To spell incorrectly
vbl. sp. A bad spelling; false orthography
And even Merriam-Webster lists "to spell (a word or name) incorrectly". So
Post by Egor Skriptunoff
It's the expectation of many programmers that a compiler should check for
misspelled identifiers and warn the user at compile time.
is, to me, be correct---'baa' is false orthography [1] of "baz" (per
Oxford); I spelled 'baz' (a word or name and in this case, it's a name)
incorrectly (per Merriam-Webster).
You and I may know that, but the compiler does not. It just sees a string.

And I deny that 'baa' is a mispelling of 'baz' - obviously it is a
misspelling of 'bar'. Or maybe 'foo'. The compiler cannot possibly know,
unless it is smart enough to know what program you intended to write.

I think you are interpreting the term
Post by Sean Conner
'misspelling' too narrowly (I do not know if English is your first language
or not) or are trolling.
Yes, I am a native speaker of English. My point is just that it is a
category error to apyly concepts like "mis (or correct) spelling" to
programming texts.
Post by Sean Conner
-spc (I'm not even sure if English is Egor's first language or not,
so I'm willing to give both of you the benefit of the doubt here)
Correct or proper spelling;
Precisely. And the only notion of correctness a compiler has is syntactic.
If it flags "baaa" as a problem it is not because it thinks it's a
misspelling of baz.
Post by Sean Conner
Here, I would aplly "any more or system of spelling" to program
identifiers. Certainly, the compiler keeps track of identifiers,
and in some cases (like C) deviations to the spelling of an
identifier can be found.
Huh? Which compiler can do that? Where in the c spec is "deviation to the
spelling of an identifier" defined?

G
Sean Conner
2018-07-05 22:28:13 UTC
Permalink
Post by Gregg Reynolds
Post by Sean Conner
Here, I would aplly "any more or system of spelling" to program
identifiers. Certainly, the compiler keeps track of identifiers,
and in some cases (like C) deviations to the spelling of an
identifier can be found.
Huh? Which compiler can do that? Where in the c spec is "deviation to the
spelling of an identifier" defined?
You, sir, are a pedantic weenie.

-spc
Sean Conner
2018-07-05 22:35:34 UTC
Permalink
Post by Gregg Reynolds
Post by Sean Conner
is, to me, be correct---'baa' is false orthography [1] of "baz" (per
Oxford); I spelled 'baz' (a word or name and in this case, it's a name)
incorrectly (per Merriam-Webster).
You and I may know that, but the compiler does not. It just sees a string.
And I deny that 'baa' is a mispelling of 'baz' - obviously it is a
misspelling of 'bar'. Or maybe 'foo'. The compiler cannot possibly know,
unless it is smart enough to know what program you intended to write.
To further clarify, when the C compiler spits out:

a.c:5: error: aa' undeclared (first use in this function)

I think, "Gee, I misspelled baz *again*. Sigh." and I go and fix it. I do
*NOT* think "Gee, I introduced an undeclared identifier; I must ponder if I
meant 'baz' or 'foo' in this instance." You are correct in that the C
compiler does not know if I meant 'baz' or 'foo'.

Then again ...

[spc]brevard:~>git statuu
git: 'statuu' is not a git-command. See 'git --help'.

Did you mean this?
status
[spc]brevard:~>

Hmmmm ...

-spc (Still consider you a pedantic weenie ... )
steve donovan
2018-07-08 10:18:35 UTC
Permalink
Post by Sean Conner
[spc]brevard:~>git statuu
git: 'statuu' is not a git-command. See 'git --help'.
Did you mean this?
status
The Rust compiler does this, when it can. Like most helpful machines,
it can be a bit ... overhelpful sometimes.

So, thinking in the context of static analyzers, a tool could flag
'prnt' and make some suggestions from nearby matching globals.

(this stuff just doesn't belong in the core)
Daurnimator
2018-07-04 05:41:49 UTC
Permalink
Post by Egor Skriptunoff
Hi!
Let me start (n+1)-th thread about "global by default" feature of Lua.
My suggestion is to replace "global by default" approach with "nothing by
$print("Hello world") -- ok
print("Hello world") -- syntax error: referencing undeclared variable
"print"
_G.print("Hello world") -- syntax error: referencing undeclared variable
"_G"
"$" is not a part of an identifier.
"$" is a lexem (for example, there could be a space between "$" and global
variable name).
"$" is absolutely the same as "_ENV." but is more comfortable to use.
Why do we need this?
1)
"$globalvar" notation introduces two separate namespaces: one for globals
and one for locals/upvalues.
As a result of this separation, most of variable name typos will be detected
at compile time.
Although global name typos will not be detected ($math.sin -> $moth.sin),
the most of identifiers in properly-written Lua programs are locals.
Currently, writing Lua programs without "global-nil-alarmer" (such as
"strict.lua") is practically impossible (because typos in local variable
names are silently converted to globals).
2)
"$print" contains more symbols than "print", and you have to press SHIFT on
your keyboard to type "$", but this is not a drawback.
Instead, there is a point in it: users would have to pay attention to slow
global access.
More finger moves = more CPU time to access.
So, we are adding "ergonomical motivation" to cache globals in Lua programs
:-)
3)
Polluting of global namespace is already discouraged in Lua, so introducing
"$" prefix for globals is the next step in that direction.
It is a polite way to say: "use globals only when they are really needed".
4)
The "$globalvar" notation will solve problem with globals occasionally
local function sort_desc(table)
table.sort(table, function(a, b) return a>b end) -- very popular
newcomers' mistake
end
5)
The "$globalvar" notation will make the difference between
"monkey-patch-friendly code" and "monkey-patch-unfriendly code" more easy to
see.
BTW, "_ENV" could be removed from Lua as "$" could do the same (with some
modifications in the parser to interpret "$" either as "_ENV." or as
$print() -- instead of print()
$.print() -- instead of print()
local env = $ -- instead of local env = _ENV
$[key] = value -- instead of _ENV[key] = value
function sndbx($) -- instead of function sndbx(_ENV)
What are your thoughts on this?
-- Egor
- Such a feature needs to be optional and opt-in, as lua is still
often used as a config file format.
- I have no general issues with global reads by default: I don't
love the doing e.g. `local type = _G.type` or similar at the top of
all my files
- We already have an opt-in of this behaviour: `local _G = _G; local
_ENV = nil` and then use e.g. `_G.print`
I think a more interesting proposal would be to make a
macro/special syntax that expands to that. ("use strict"?)
Russell Haley
2018-07-04 06:04:23 UTC
Permalink
On Tue, Jul 3, 2018 at 10:26 PM, Egor Skriptunoff <
Post by Egor Skriptunoff
Hi!
Let me start (n+1)-th thread about "global by default" feature of Lua.
My suggestion is to replace "global by default" approach with "nothing by
$print("Hello world") -- ok
print("Hello world") -- syntax error: referencing undeclared variable
"print"
_G.print("Hello world") -- syntax error: referencing undeclared variable
"_G"
"$" is not a part of an identifier.
"$" is a lexem (for example, there could be a space between "$" and global
variable name).
"$" is absolutely the same as "_ENV." but is more comfortable to use.
Why do we need this?
1)
"$globalvar" notation introduces two separate namespaces: one for globals
and one for locals/upvalues.
As a result of this separation, most of variable name typos will be
detected at compile time.
Although global name typos will not be detected ($math.sin -> $moth.sin),
the most of identifiers in properly-written Lua programs are locals.
Currently, writing Lua programs without "global-nil-alarmer" (such as
"strict.lua") is practically impossible (because typos in local variable
names are silently converted to globals).
2)
"$print" contains more symbols than "print", and you have to press SHIFT
on your keyboard to type "$", but this is not a drawback.
Instead, there is a point in it: users would have to pay attention to slow
global access.
More finger moves = more CPU time to access.
So, we are adding "ergonomical motivation" to cache globals in Lua
programs :-)
3)
Polluting of global namespace is already discouraged in Lua, so
introducing "$" prefix for globals is the next step in that direction.
It is a polite way to say: "use globals only when they are really needed".
4)
The "$globalvar" notation will solve problem with globals occasionally
local function sort_desc(table)
table.sort(table, function(a, b) return a>b end) -- very popular
newcomers' mistake
end
5)
The "$globalvar" notation will make the difference between
"monkey-patch-friendly code" and "monkey-patch-unfriendly code" more easy
to see.
BTW, "_ENV" could be removed from Lua as "$" could do the same (with some
modifications in the parser to interpret "$" either as "_ENV." or as
$print() -- instead of print()
$.print() -- instead of print()
local env = $ -- instead of local env = _ENV
$[key] = value -- instead of _ENV[key] = value
function sndbx($) -- instead of function sndbx(_ENV)
What are your thoughts on this?
I'm just now reading about Lua in Garry's Mod and it seems to me they've
"polluted" the global space with this thing called an API. I don't know
anything about the details yet but it looks pretty handy. Tee hee. All
joking aside, I avoid using global but I "don't know why" (do I dare
conjure C++ namespaces in the discussion?). Personally, if I wanted a way
of not typing 'local' all the time, I would prefer to see a keyword at the
top of a file such as "$LOCAL_DEFAULT" and then have to type 'global' to
alter the scope, but I suspect Lua.org has already thought things like that
through and rejected the idea. A nice use case for LHR's lptoken.

I'm not fond of Javascript scope shenanigans. I think simple (explicit) is
good in scope declaration and strict is our friend; though I don't often
use strict and suffer the consequences.

Russ
Post by Egor Skriptunoff
-- Egor
Axel Kittenberger
2018-07-04 07:06:50 UTC
Permalink
Post by Russell Haley
I'm not fond of Javascript scope shenanigans. I think simple (explicit) is
good in scope declaration and strict is our friend; though I don't often
use strict and suffer the consequences.
Javascript scoping has recently greatly improved with using 'let' instead
of 'var'.

In creating variables (or reading those that don't exist) I still don't get
it, why default anything should ever be a good idea, it's just an
invitation to bugs due to spelling mistakes.

And yes this applies to config files as well. I used Lua like this and got
negative feedback of people complaining there wasn't any notification
because they misspelled a variable. So instead after the user config file
finished, I made a loop that checks if any unknown variables are in global
space and error if so.

For another case, this is a simplified version for locking globals:
---
local t = _G
local mt = getmetatable( t ) or { }
mt.__index = function( t, k )
if k ~= '_' and string.sub( k, 1, 2 ) ~= '__'
then
error( 'Access of non-existing global "' .. k ..'"', 2 )
else
rawget( t, k )
end
end

mt.__newindex = function( t, k, v )
if k ~= '_' and string.sub( k, 1, 2 ) ~= '__'
then
error( 'implicit global ', 2 )
else
rawset( t, k, v )
end
end

function lockGlobals( )
setmetatable( t, mt )
end
----
I don't remember why I made exceptions for _ and __ and if these are used
to access _G in the first place.
Sean Conner
2018-07-04 07:28:47 UTC
Permalink
Post by Axel Kittenberger
And yes this applies to config files as well. I used Lua like this and got
negative feedback of people complaining there wasn't any notification
because they misspelled a variable. So instead after the user config file
finished, I made a loop that checks if any unknown variables are in global
space and error if so.
For this use case, I think it would be easier to do this:

CONF =
{
host = "localhost",
port = 8080,
datadir = '/tmp',
syslog =
{
id = 'my-daemon',
facility = 'local1',
},
}

setmetatable(CONF,{
__newindex = function(_,key)
error(string.format("invalid config parameter: %s",key),2)
end
})

f = loadfile(arg[1] or "config.txt","t",CONF)
okay,err = pcall(f)
if not okay then print(err) end

You can set default values, and you get error checking:

[spc]lucy:/tmp/bar>lua-53 read.lua
config.txt:2: invalid config parameter: plort
[spc]lucy:/tmp/bar>

[spc]lucy:/tmp/bar>lua-53 read.lua
config.txt:5: attempt to index a nil value (global 'sylog')
[spc]lucy:/tmp/bar>

-spc
Egor Skriptunoff
2018-07-04 20:33:15 UTC
Permalink
Post by Russell Haley
I'm just now reading about Lua in Garry's Mod and it seems to me they've
"polluted" the global space with this thing called an API. I don't know
anything about the details yet but it looks pretty handy.
Yes, all game scripting systems expose their API as hundreds of global
objects/functions/variables.
It looks pretty handy indeed, but there is a small problem here.
For example, in Garry's Mod there are global names (belonging to API) such
as
Vector, Sound, Player, Path, Entity, Color, Angle
which could be occasionally shadowed out by local variables with the same
name.
This is quite popular mistake, because it is hard to keep in mind whole
huge API.
When reading a script, it may be not obvious where variable "Vector" comes
from: is it API function or local variable?
"$" prefix would be useful here: it would act as a bright indicator "from
API"/"not from API", so most of api-object-was-shadowed-out mistakes would
disappear.
Marc Balmer
2018-07-04 07:13:03 UTC
Permalink
Post by Egor Skriptunoff
Hi!
Let me start (n+1)-th thread about "global by default" feature of Lua.
$print("Hello world") -- ok
print("Hello world") -- syntax error: referencing undeclared variable "print"
_G.print("Hello world") -- syntax error: referencing undeclared variable "_G"
"$" is not a part of an identifier.
"$" is a lexem (for example, there could be a space between "$" and global variable name).
"$" is absolutely the same as "_ENV." but is more comfortable to use.
Why do we need this?
1)
"$globalvar" notation introduces two separate namespaces: one for globals and one for locals/upvalues.
As a result of this separation, most of variable name typos will be detected at compile time.
Although global name typos will not be detected ($math.sin -> $moth.sin), the most of identifiers in properly-written Lua programs are locals.
Currently, writing Lua programs without "global-nil-alarmer" (such as "strict.lua") is practically impossible (because typos in local variable names are silently converted to globals).
2)
"$print" contains more symbols than "print", and you have to press SHIFT on your keyboard to type "$", but this is not a drawback.
Instead, there is a point in it: users would have to pay attention to slow global access.
More finger moves = more CPU time to access.
So, we are adding "ergonomical motivation" to cache globals in Lua programs :-)
3)
Polluting of global namespace is already discouraged in Lua, so introducing "$" prefix for globals is the next step in that direction.
It is a polite way to say: "use globals only when they are really needed".
4)
local function sort_desc(table)
table.sort(table, function(a, b) return a>b end) -- very popular newcomers' mistake
end
5)
The "$globalvar" notation will make the difference between "monkey-patch-friendly code" and "monkey-patch-unfriendly code" more easy to see.
$print() -- instead of print()
$.print() -- instead of print()
local env = $ -- instead of local env = _ENV
$[key] = value -- instead of _ENV[key] = value
function sndbx($) -- instead of function sndbx(_ENV)
What are your thoughts on this?
It's a bad idea. Very bad.
Post by Egor Skriptunoff
-- Egor
Petri Häkkinen
2018-07-04 07:39:16 UTC
Permalink
The last time I checked our work in progress codebase of a game project had about 2000 global functions. Nothing wrong with them. Actually, it’s pretty handy to be able to live update any of them. Plus autocompletion, ref browsing and other IDE must-haves work out of the box because there’s no renaming / namespacing going on.

”globals are evil” usually refers to mutable global state. We have that too, although we try to avoid it if possible (grouping global vars into namespaces helps).

With this backstory you probably understand why having to prefix every global with $ would make our eyes hurt...

I also think typos in variable names are pretty easy to find and fix. On the other hand when doing large refactorings to the codebase, some sort of optional static type checking for function args and automatic type inference for vars would be very useful. A much more difficult problem unfortunately...

Cheers,

Petri
Egor Skriptunoff
2018-07-04 19:41:54 UTC
Permalink
Post by Petri Häkkinen
you probably understand why having to prefix every global with $ would
make our eyes hurt...
Actually I didn't understand why.
Post by Petri Häkkinen
I also think typos in variable names are pretty easy to find and fix.
I don't think so.
Typo in local variable name may result in hard-to-find bug.
Sean Conner
2018-07-04 20:06:25 UTC
Permalink
Post by Egor Skriptunoff
Post by Petri Häkkinen
you probably understand why having to prefix every global with $ would
make our eyes hurt...
Actually I didn't understand why.
I can't give an objective reason, but for me, using sigils for scope
(which is what Ruby does if I recall correctly) triggers my aesthetic
sensibilities.

Anyone can get used to anything [1], thus the subjectivity.
Post by Egor Skriptunoff
Post by Petri Häkkinen
I also think typos in variable names are pretty easy to find and fix.
I don't think so.
Typo in local variable name may result in hard-to-find bug.
I've used luacheck to find typos and inadvertant globals. It's easy to
use, and if you use some form of source control, most give you a way to run
scripts prior to code checkin, so you could have the checkin fail if
luacheck finds an issue.

Does it suck to have to use another tool? I don't know. For me, it's
worth it.

-spc

[1] http://boston.conman.org/2008/01/04.1

Yes, I was used to seeing BASIC presented that way. Doesn't mean I
would accept that now. I got better.
Pierre-Yves Gérardy
2018-07-04 07:22:09 UTC
Permalink
On Wed, Jul 4, 2018 at 7:26 AM, Egor Skriptunoff
Post by Egor Skriptunoff
"$" is not a part of an identifier.
"$" is a lexem (for example, there could be a space between "$" and global
variable name).
"$" is absolutely the same as "_ENV." but is more comfortable to use.
Making global access explicit but light is actually a good idea IMO.

The specific use of `$` is reminiscent of Perl and PHP though. `@` is
also available and I'd expect it to be less controversial.

—Pierre-Yves
Sean Conner
2018-07-04 07:29:36 UTC
Permalink
Post by Pierre-Yves Gérardy
On Wed, Jul 4, 2018 at 7:26 AM, Egor Skriptunoff
Post by Egor Skriptunoff
"$" is not a part of an identifier.
"$" is a lexem (for example, there could be a space between "$" and global
variable name).
"$" is absolutely the same as "_ENV." but is more comfortable to use.
Making global access explicit but light is actually a good idea IMO.
also available and I'd expect it to be less controversial.
Nope. If I want to program in Perl (or Ruby for that matter), I know
where to find it.

-spc
Pierre Chapuis
2018-07-04 08:47:13 UTC
Permalink
My take on this is: this is not really necessary, just use luacheck.

The default top-level environment (`_G`) could maybe have a metatable
that raises an error on access by default (à la `strict.lua`). It would
encourage modules to do the right thing.
The ability to override this on a given `_ENV` is critical for DSLs
(configuration files etc).
But mostly, use luacheck systematically...
Hi!
Let me start (n+1)-th thread about "global by default" feature of Lua.>
My suggestion is to replace "global by default" approach with "nothing
by default" by introducing special syntax for accessing global
variables:>
$print("Hello world") -- ok print("Hello world") -- syntax
error: referencing undeclared variable "print" _G.print("Hello world")
-- syntax error: referencing undeclared variable "_G"
Post by Egor Skriptunoff
"$" is not a part of an identifier.
"$" is a lexem (for example, there could be a space between "$" and
global variable name).> "$" is absolutely the same as "_ENV." but is more comfortable to use.>
Why do we need this?
1)
"$globalvar" notation introduces two separate namespaces: one for
globals and one for locals/upvalues.> As a result of this separation, most of variable name typos will be
detected at compile time.> Although global name typos will not be detected ($math.sin ->
$moth.sin), the most of identifiers in properly-written Lua programs
are locals.> Currently, writing Lua programs without "global-nil-alarmer" (such as
"strict.lua") is practically impossible (because typos in local
variable names are silently converted to globals).>
2)
"$print" contains more symbols than "print", and you have to press
SHIFT on your keyboard to type "$", but this is not a drawback.> Instead, there is a point in it: users would have to pay attention to
slow global access.> More finger moves = more CPU time to access.
So, we are adding "ergonomical motivation" to cache globals in Lua
programs :-)>
3)
Polluting of global namespace is already discouraged in Lua, so
introducing "$" prefix for globals is the next step in that direction.> It is a polite way to say: "use globals only when they are really
needed".>
4)
The "$globalvar" notation will solve problem with globals occasionally
shadowed out by locals or upvalues:>
local function sort_desc(table) table.sort(table, function(a, b)
return a>b end) -- very popular newcomers' mistake end
Post by Egor Skriptunoff
5)
The "$globalvar" notation will make the difference between "monkey-patch-
friendly code" and "monkey-patch-unfriendly code" more easy to see.>
BTW, "_ENV" could be removed from Lua as "$" could do the same (with
some modifications in the parser to interpret "$" either as "_ENV." or
as "_ENV"):>
$print() -- instead of print() $.print() -- instead
of print() local env = $ -- instead of local env = _ENV $[key] =
value -- instead of _ENV[key] = value function sndbx($) --
instead of function sndbx(_ENV)> What are your thoughts on this?
-- Egor
Egor Skriptunoff
2018-07-04 19:48:14 UTC
Permalink
Post by Pierre Chapuis
My take on this is: this is not really necessary, just use luacheck.
Yes, using special 3rd party software for checking Lua scripts is a true
solution.
But I think checking for misspelled variable names is quite important to be
inside Lua core.
Sean Conner
2018-07-04 20:16:59 UTC
Permalink
Post by Egor Skriptunoff
Post by Pierre Chapuis
My take on this is: this is not really necessary, just use luacheck.
Yes, using special 3rd party software for checking Lua scripts is a true
solution.
But people use third party software for debugging, aka debuggers.
luacheck is just a special type of debugger. Heck, a lot of programmers use
IDEs and simply can't deal with using a normal text editor. Is that a
crutch? [1]
Post by Egor Skriptunoff
But I think checking for misspelled variable names is quite important to be
inside Lua core.
And yet, Lua doesn't warn me when I inadvertantly reassigned a variable
with a different type [2] and *that* error is just as nasty as a typo ...

-spc (So, how much do we protect ourselves from ourselves?)

[1] http://boston.conman.org/2009/11/02.1
http://boston.conman.org/2009/11/03.1

[2] That bit be recently. I had [3]:

local url = require "org.conman.parsers.url.url"
local lpeg = require "lpeg"

-- ...

local seconds = P"T"
local remoteuser = (modifier * P"u")
/ function() return Cg(e_atom,"ruser") end
local url = P"U"
local servername = P"v"

-- ...

local pat = apache:match[[[[%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{outstream}n/%{instream}n (%{ratio}n%%)]]

-- ...

data = pat:match(log_entry)
data['Referer'] = url:match(data['Referer'])
-- oops!

[3] Code still isn't finished.
Pierre Chapuis
2018-07-04 08:50:24 UTC
Permalink
Post by Petri Häkkinen
”globals are evil” usually refers to mutable global state. We have that
too, although we try to avoid it if possible (grouping global vars into
namespaces helps).
And modules. Don't use globals in modules. You never know when you will cause a silent collision with something else.
Viacheslav Usov
2018-07-04 09:28:19 UTC
Permalink
Post by Egor Skriptunoff
My suggestion is to replace "global by default" approach with "nothing by
default" by introducing special syntax for accessing global variables:

While the desire to do away with implicit globals is perfectly
understandable and probably shared by many users of Lua, the proposal
introduces strong incompatibilities. The $ prefix seems, to me, like an
ugly wart purely aesthetically, plus on some keyboards fetching the dollar
sign can be complicated.

But perhaps there is no need to reinvent the wheel in this area.

A popular family of programming languages, BASIC, stared off with implicit
declaration of variables. Later at some point it was realised that the
implicit declaration was problematic, and the OPTION EXPLICIT statement was
added t the language. It was opt-in originally. In some later derivatives
such as Visual Basic, it works as follows:

If OPTION EXPLICIT ON/OFF is present in a module, then it controls the
declaration mode in that module.

Otherwise, it is controlled in "project settings" or "command line".

Now, Lua is not BASIC, but I suggest that the following scheme might work:

1. Any Lua state has an explicit/implicit global declaration setting. The
default 'explcit' vs 'implicit' is a constant chosen when compiling the Lua
engine, with 'implicit' by default, so that existing code is fully
unaffected by this.
2. The global declaration setting can be changed through C API. It is
debatable whether an equivalent of the API should be available in the Lua
land.
3. Any API, C or Lua, that allows loading/compiling a Lua chunk gets an
optional parameter that controls the global declaration mode while
compiling that chunk.If the declaration mode argument is specified, it
overrides the Lua state's declaration setting, while compiling that chunk.
Otherwise the Lua state's setting applies.
4. It is debatable whether the declaration mode parameter should have a
flag such as "make this the default declaration mode when that chunk loads
further chunks".
5. A new statement is provided so that the global declaration mode can be
specified within a Lua chunk (similar to OPTION EXPLICIT in BASIC). If it
is present, it overrides the effective declaration mode within the chunk
(when compiling the rest of the chunk). It is debatable whether this
statement needs to be scoped, and whether it can be specified multiple
times within a chunk, and whether it could be inherited by chunks loaded
from this chunk (c.f. #4).
6. A new statement is provided to declare globals.
7. During compilation, when the effective declaration mode is explicit, and
an identifier is encountered that has not been declared previously as a
global or as a local, a compile time error is raised.

Now, bikeshedding.

Today, syntax like "not local something" is ill-formed.

8. The new statement "not local = explicit" sets the explicit global
declaration mode. I further suggest that 'explicit' in that statement
should not by itself be a reserved keyword outside the statement.
9. The new statement "not local = implicit" sets the implicit global
declaration mode. I further suggest that ' implicit ' in that statement
should not by itself be a reserved keyword outside the statement.
10. The new statement "not local foo, bar, etc" declares foo, bar, etc as
global variables. Note it is only a declaration, it does not initialise the
global variables in any way.

With this syntax, globals would be slightly more verbose to declare than
locals, which I think is a good thing. Other than this, once declared, they
would not be any different from today's globals in use.

This proposal is fully backward compatible as far as I can tell, and it
allows both opt-in and opt-out for implementations.

Cheers,
V.
Etiene Dalcol
2018-07-04 10:02:21 UTC
Permalink
Post by Pierre Chapuis
My take on this is: this is not really necessary, just use luacheck.
I agree with this. The easiest eay to solve this immediately is simply to
add a linter to your text editor or run luacheck from the cmd line
Post by Pierre Chapuis
On Wed, Jul 4, 2018 at 7:26 AM Egor Skriptunoff <
Post by Egor Skriptunoff
My suggestion is to replace "global by default" approach with "nothing
While the desire to do away with implicit globals is perfectly
understandable and probably shared by many users of Lua, the proposal
introduces strong incompatibilities. The $ prefix seems, to me, like an
ugly wart purely aesthetically, plus on some keyboards fetching the dollar
sign can be complicated.
But perhaps there is no need to reinvent the wheel in this area.
A popular family of programming languages, BASIC, stared off with implicit
declaration of variables. Later at some point it was realised that the
implicit declaration was problematic, and the OPTION EXPLICIT statement was
added t the language. It was opt-in originally. In some later derivatives
If OPTION EXPLICIT ON/OFF is present in a module, then it controls the
declaration mode in that module.
Otherwise, it is controlled in "project settings" or "command line".
1. Any Lua state has an explicit/implicit global declaration setting. The
default 'explcit' vs 'implicit' is a constant chosen when compiling the Lua
engine, with 'implicit' by default, so that existing code is fully
unaffected by this.
2. The global declaration setting can be changed through C API. It is
debatable whether an equivalent of the API should be available in the Lua
land.
3. Any API, C or Lua, that allows loading/compiling a Lua chunk gets an
optional parameter that controls the global declaration mode while
compiling that chunk.If the declaration mode argument is specified, it
overrides the Lua state's declaration setting, while compiling that chunk.
Otherwise the Lua state's setting applies.
4. It is debatable whether the declaration mode parameter should have a
flag such as "make this the default declaration mode when that chunk loads
further chunks".
5. A new statement is provided so that the global declaration mode can be
specified within a Lua chunk (similar to OPTION EXPLICIT in BASIC). If it
is present, it overrides the effective declaration mode within the chunk
(when compiling the rest of the chunk). It is debatable whether this
statement needs to be scoped, and whether it can be specified multiple
times within a chunk, and whether it could be inherited by chunks loaded
from this chunk (c.f. #4).
6. A new statement is provided to declare globals.
7. During compilation, when the effective declaration mode is explicit,
and an identifier is encountered that has not been declared previously as a
global or as a local, a compile time error is raised.
Now, bikeshedding.
Today, syntax like "not local something" is ill-formed.
8. The new statement "not local = explicit" sets the explicit global
declaration mode. I further suggest that 'explicit' in that statement
should not by itself be a reserved keyword outside the statement.
9. The new statement "not local = implicit" sets the implicit global
declaration mode. I further suggest that ' implicit ' in that statement
should not by itself be a reserved keyword outside the statement.
10. The new statement "not local foo, bar, etc" declares foo, bar, etc as
global variables. Note it is only a declaration, it does not initialise the
global variables in any way.
With this syntax, globals would be slightly more verbose to declare than
locals, which I think is a good thing. Other than this, once declared, they
would not be any different from today's globals in use.
This proposal is fully backward compatible as far as I can tell, and it
allows both opt-in and opt-out for implementations.
Cheers,
V.
--
Etiene Dalcol

Software Engineer and NLP Researcher
Sailor http://sailorproject.org
Lua Space http://lua.space
LuaConf http://luaconf.com
Viacheslav Usov
2018-07-04 10:18:29 UTC
Permalink
Post by Etiene Dalcol
Post by Pierre Chapuis
My take on this is: this is not really necessary, just use luacheck.
I agree with this. The easiest eay to solve this immediately is simply to
add a linter to your text editor or run luacheck from the cmd line
This is wishful thinking. Grapple with the fact that various forms of
restricting "implicit global" have existed for over a decade, yet they are
not deemed sufficient.

Cheers,
V.
Soni "They/Them" L.
2018-07-04 10:43:42 UTC
Permalink
Post by Etiene Dalcol
Post by Pierre Chapuis
My take on this is: this is not really necessary, just use luacheck.
I agree with this. The easiest eay to solve this immediately is
simply to add a linter to your text editor or run luacheck from
the cmd line
This is wishful thinking. Grapple with the fact that various forms of
restricting "implicit global" have existed for over a decade, yet they
are not deemed sufficient.
Cheers,
V.
I've been using an IDE (ZBS) "lint" that highlights all global access.
It's more than enough.
Viacheslav Usov
2018-07-04 10:48:53 UTC
Permalink
Post by Soni "They/Them" L.
I've been using an IDE (ZBS) "lint" that highlights all global access.
In the entire umpteen-deep tree of modules your program loads. Sure, I *so*
believe you.
Post by Soni "They/Them" L.
It's more than enough.
"Wishful thinking is the formation of beliefs and making decisions
according to what might be pleasing to imagine instead of by appealing to
evidence, rationality, or reality." [1]

Cheers,
V.

[1] https://en.wikipedia.org/wiki/Wishful_thinking
Thijs Schreijer
2018-07-04 11:21:52 UTC
Permalink
Post by Pierre Chapuis
My take on this is: this is not really necessary, just use luacheck.
I agree with this. The easiest eay to solve this immediately is simply to add a linter to your text editor or run luacheck from the cmd line

This is wishful thinking. Grapple with the fact that various forms of restricting "implicit global" have existed for over a decade, yet they are not deemed sufficient.

Hmmm, claiming someone is “wishfully thinking" (defined as per your later post, as liked, imagined but without evidence), and then stating “they are not deemed sufficient”, which lacks evidence, is a slightly odd way of reasoning imo.

And it is extra controversial imo since you're arguing against a post from someone claiming they actually were sufficient.


Cheers,
V.


I for one mostly use the ZBS linter, and LuaCheck in CI. Covers my cases very well. Additionally I like the ability to use Lua as a data description language for config files and the likes.

Thijs
Viacheslav Usov
2018-07-04 11:45:59 UTC
Permalink
Post by Thijs Schreijer
stating “they are not deemed sufficient”, which lacks evidence, is a
slightly odd way of reasoning imo.

I did refer to the fact that the mechanisms to restrict implicit globals
were known for over a decade; the fact that we are having this discussion
again (N + 1, as said by the original poster), with participants evidently
aware of those mechanisms, means they are considered insufficient.
Post by Thijs Schreijer
you're arguing against a post from someone claiming they actually were
sufficient.

When they are claiming "it is sufficient", their true statement is "it is
sufficient for me", where 'for me' is a shorthand for 'under some not fully
disclosed conditions'. All one can take away from that is they are
personally fine with implicit globals at least right now; my proposal is
compatible with that.
Post by Thijs Schreijer
I for one mostly use the ZBS linter, and LuaCheck in CI. Covers my cases
very well. Additionally I like the ability to use Lua as a data description
language for config files and the likes.

So you are claiming the same 'for me' thing. Your use of Lua would be fully
compatible with my proposal. Static analysis tools, specifically, can only
benefit from explicit global declarations.

Cheers,
V.
Thijs Schreijer
2018-07-04 12:30:35 UTC
Permalink
Post by Thijs Schreijer
stating “they are not deemed sufficient”, which lacks evidence, is a slightly odd way of reasoning imo.
I did refer to the fact that the mechanisms to restrict implicit globals were known for over a decade; the fact that we are having this discussion again (N + 1, as said by the original poster), with participants evidently aware of those mechanisms, means they are considered insufficient.

The folks that are satisfied with the current mechanisms, or that don’t have an issue with globals at all, do not start those discussions. Only the ones that are not satisfied do. Now concluding that because you start a discussion, that it “evidently” means others peoples problems haven’t been solved, and that the “general audience” still has an issue, is a rather big claim.

I honestly wonder what % of the community really thinks this is a problem worth solving.
Post by Thijs Schreijer
you're arguing against a post from someone claiming they actually were sufficient.
When they are claiming "it is sufficient", their true statement is "it is sufficient for me", where 'for me' is a shorthand for 'under some not fully disclosed conditions'. All one can take away from that is they are personally fine with implicit globals at least right now; my proposal is compatible with that.

This argument equals your statement of “not deemed sufficient”. By what measure “sufficient"?
Post by Thijs Schreijer
I for one mostly use the ZBS linter, and LuaCheck in CI. Covers my cases very well. Additionally I like the ability to use Lua as a data description language for config files and the likes.
So you are claiming the same 'for me' thing. Your use of Lua would be fully compatible with my proposal. Static analysis tools, specifically, can only benefit from explicit global declarations.

No. I was not claiming anything. Just mentioned how I deal with it. Don’t get me wrong, I’m not necessarily against solutions to this “perceived problem”. And I didn’t even respond to your proposal, only to your reasoning.



Cheers,
V.
Enrico Colombini
2018-07-04 12:40:28 UTC
Permalink
The folks that are satisfied with the current mechanisms, or that don’t
have an issue with globals at all, do not start those discussions. Only
the ones that are not satisfied do. Now concluding that because you
start a discussion, that it “evidently” means others peoples problems
haven’t been solved, and that the “general audience” still has an issue,
is a rather big claim.
I honestly wonder what % of the community really thinks this is a problem worth solving.
Not me, for what little is worth.
(by the way, I think Dirk showed how to think in Lua, rather than trying
to bend the language to suit one's habits)
--
Enrico
Viacheslav Usov
2018-07-04 13:02:52 UTC
Permalink
On Wed, Jul 4, 2018 at 2:33 PM Thijs Schreijer <***@thijsschreijer.nl>
wrote:

(1) > stating “they are not deemed sufficient”, which lacks evidence, is a
slightly odd way of reasoning imo.

(2) > The folks that are satisfied with the current mechanisms, or that
don’t have an issue with globals at all, do not start those discussions.
Only the ones that are not satisfied do.

So you admit, in (2), that there are some people who are "not satisfied".
Yet in (1) you insisted there was no evidence of "not deemed sufficient". I
honestly cannot connect these two statements of yours.
Post by Thijs Schreijer
Now concluding that because you start a discussion, that it “evidently”
means others peoples problems haven’t been solved, and that the “general
audience” still has an issue, is a rather big claim.

I did not make such conclusions, so I am not sure what you are arguing with.

It is evident that (A) "some people are satisfied" and (B) "some people are
not satisfied". I proposed something that would be suitable for both camps,
not requiring camp (A) to do anything at all.

Now I get responses from camp (A) that "this is unnecessary", because, drum
roll,, they are camp (A).
Post by Thijs Schreijer
This argument equals your statement of “not deemed sufficient”. By what
measure “sufficient"?

Per (1) and (2), you contradict yourself when talking about “not deemed
sufficient”. I am afraid you will need to clarify your position here.
Post by Thijs Schreijer
And I didn’t even respond to your proposal, only to your reasoning.
Ah, great. Arguing for the same of arguing, in the middle of somebody
else's discussion.

Cheers,
V.
Viacheslav Usov
2018-07-04 13:36:32 UTC
Permalink
Post by Thijs Schreijer
I honestly wonder what % of the community really thinks this is a problem worth solving.
Cannot say for the global community, but of those contributing to the
thread:

Worth solving:

Egor
Steven
Russel
Axel
Pierre-Yves
myself
Total: 6

Not worth solving:

Sean
Petri
Pierre Chapuis
Etiene
Dirk
Soni
Enrico
Total: 7

Neutral/unclear:

Daurnimator
Marc
Thijs

Grand total: 16

So, 38% vs 44% so far.

Sorry for any misinterpretation and misspelling of names. Please feel free
to correct me.

Cheers,
V.
Marc Balmer
2018-07-05 06:46:55 UTC
Permalink
Post by Viacheslav Usov
Post by Thijs Schreijer
I honestly wonder what % of the community really thinks this is a problem worth solving.
Egor
Steven
Russel
Axel
Pierre-Yves
myself
Total: 6
Sean
Petri
Pierre Chapuis
Etiene
Dirk
Soni
Enrico
Total: 7
Daurnimator
Marc
Thijs
How was I unclear or neutral when I wrote "It's a bad idea?". In case you need a more explicit statement: Globals are fine as they are.
Post by Viacheslav Usov
Grand total: 16
So, 38% vs 44% so far.
Sorry for any misinterpretation and misspelling of names. Please feel free to correct me.
Cheers,
V.
Viacheslav Usov
2018-07-05 08:40:04 UTC
Permalink
Post by Marc Balmer
How was I unclear or neutral when I wrote "It's a bad idea?".
That was not in response to "is this a problem worth solving", and there
was nothing else in your response.

Thanks for stating your opinion unambiguously.

Cheers,
V.
Dirk Laurie
2018-07-05 10:11:55 UTC
Permalink
Post by Viacheslav Usov
Post by Marc Balmer
How was I unclear or neutral when I wrote "It's a bad idea?".
That was not in response to "is this a problem worth solving",
So the OP's diatribe against globals is to be split in three parts,
each requiring that its predecessor is taken for granted.

(a) the status quo is bad;
(b) we need a way to specify whether a variable is global;
(c) one such way is to put a dollar sign in front of the name.

and one can agree with zero, one, two or all three of these.

It does seem to be an oversimplification to count only for and against.
Here is a finer classification (I have omitted the unclear ones):

0: Daurnimator, Sean, Marc, Petri, Pierre, Etiene, Dirk, Soni, Thijs,
Gregg, Enrico
1: Steven
2: Pierre-Yves, Viacheslav
3: Egor, Jakub
Viacheslav Usov
2018-07-05 10:26:57 UTC
Permalink
Post by Dirk Laurie
0: Daurnimator, Sean, Marc, Petri, Pierre, Etiene, Dirk, Soni, Thijs,
Gregg, Enrico

When I was going over the thread yesterday, I do no think I gathered
that Daurnimator and Thijs clearly stated "keep the status quo".

You miscounted me; my proposal was about "make the default configurable,
keeping the default default as is", with what seemed like natural
consequences from that.

Where are Axel and Russel in your tally?

Cheers,
V.
Axel Kittenberger
2018-07-05 10:36:25 UTC
Permalink
Post by Viacheslav Usov
Where are Axel and Russel in your tally?
Nope, but it doesn't matter. I find this kind of "vote" counting just as
useless as this "silent majority" argument in that other thread.
Viacheslav Usov
2018-07-05 10:41:05 UTC
Permalink
Post by Axel Kittenberger
Nope, but it doesn't matter. I find this kind of "vote" counting just as
useless as this "silent majority" argument in that other thread.

If you did have an opinion as to subject of the thread, and if somebody
bothers counting those opinions, they should be counted accurately, even if
you do not care being counted.

Cheers,
V.
Dirk Laurie
2018-07-05 10:55:04 UTC
Permalink
Post by Dirk Laurie
0: Daurnimator, Sean, Marc, Petri, Pierre, Etiene, Dirk, Soni, Thijs,
Gregg, Enrico
When I was going over the thread yesterday, I do no think I gathered that
Daurnimator and Thijs clearly stated "keep the status quo".
They did not clearly state "the status quo is bad" and explained how
they cope with the difficulty.

Thijs did state explicitly that he was 'not necessarily against
solutions to this “perceived problem”', so if you want to count that
as undecided, I suppose you can. But in that case anybody who grants
that default globals are a difficulty but who are satisfied with
runtime ways of dealing with them, might be so classified, even me,
though my attitude is simply "if ain't borken, don't fix it". I prefer
to see Thijs's attitude as the classical liberal one of keeping an
open mind.
You miscounted me; my proposal was about "make the default configurable,
keeping the default default as is", with what seemed like natural
consequences from that.
If that makes you a 0: welcome to the club!
Where are Axel and Russel in your tally?
Axel has replied while I am typing.

Russell said "I'm not fond of Javascript scope shenanigans" and
"strict is your friend", but then admitted to not being a very regular
user of "strict". I was willing to leave that as "undecided".
Viacheslav Usov
2018-07-05 11:19:19 UTC
Permalink
They did not clearly state "the status quo is bad" and explained how they
cope with the difficulty.

I do not think this is enough to count them in group 0. Especially if you
invoke the notion of "the classical liberal one of keeping an open mind";
an "open mind" mistrusts any status quo just about by definition.
If that makes you a 0: welcome to the club!
Nope, you cannot disregard me as a 0. I definitely do think that "the
status quo is bad".
Axel has replied while I am typing.
Not that he is undecided.
then admitted to not being a very regular user of "strict".
... "and suffer the consequences", he said, having said previously "I would
prefer to see a keyword at the top of a file such as "$LOCAL_DEFAULT" and
then have to type 'global' to alter the scope".
I was willing to leave that as "undecided".
Very interesting.

Cheers,
V.
Pierre-Yves Gérardy
2018-07-05 11:47:25 UTC
Permalink
Post by Dirk Laurie
Post by Viacheslav Usov
Post by Marc Balmer
How was I unclear or neutral when I wrote "It's a bad idea?".
That was not in response to "is this a problem worth solving",
So the OP's diatribe against globals is to be split in three parts,
each requiring that its predecessor is taken for granted.
(a) the status quo is bad;
(b) we need a way to specify whether a variable is global;
(c) one such way is to put a dollar sign in front of the name.
I'd add a distinction between folks who think the way globals are
handled should stay the way it is and folks who are fine with it as is
but wouldn't mind if it changed.

I'd expect many Lua users to fall in that category.

Or folks who are split on the question. From a language standpoint, I
think it would be nice to have a distinct syntax for locals and
globals. From an ecosystem point of view, I'd be wary of such a
change.

A possible half-solution (that would trigger runtime errors) based on
the current language would be to do

local _, _ENV = _ENV, nil

You can replace `nil` with a table whose `__index` and `__newindex`
metamethods throw nicer errors (I have a `noglobals()` helper for that
with Lua 5.1 compat as well).

Then you can access `_.print`, etc, which is syntactically distinct
from locals. Compiler errors would still be better though.

—Pierre-Yves
Dirk Laurie
2018-07-05 15:54:25 UTC
Permalink
Post by Pierre-Yves Gérardy
Post by Dirk Laurie
Post by Viacheslav Usov
Post by Marc Balmer
How was I unclear or neutral when I wrote "It's a bad idea?".
That was not in response to "is this a problem worth solving",
So the OP's diatribe against globals is to be split in three parts,
each requiring that its predecessor is taken for granted.
(a) the status quo is bad;
(b) we need a way to specify whether a variable is global;
(c) one such way is to put a dollar sign in front of the name.
I'd add a distinction between folks who think the way globals are
handled should stay the way it is and folks who are fine with it as is
but wouldn't mind if it changed.
I'd expect many Lua users to fall in that category.
Well, I am in that category. I wouldn't mind if it changed, provided
that the change is non-breaking.

I don't think, though, that a non-breaking change (or even
a breaking change) is possible before runtime. The reason
for that is that the distinction between compile time and
runtime is illusory in any interpreted language that offers
a function like `load`.

And as I and others have pointed out repeatedly, it is already
possible, even easy, to obtain the desired effect at runtime.

So I simply think the whole thread was sparked by a non-solution
to a non-problem.
Frank Kastenholz
2018-07-05 17:51:49 UTC
Permalink
It seems to me that the biggest real problem with global-by-default is not actually the globalness of the variables [1] but rather the automatic creation of those variables. This is what leads to hard to find bugs. The foo/bar/baz/baa example shows this quite nicely.

One could imagine a mechanism where tables get locked - new keys are not allowed to be added to locked tables, but existing keys could be used in the usual way[2] One could then further imagine something like
_ENV.global1=...
_ENV.global2=...
_ENV.global3=...
Lock(ENV_)
The foo/bar/baz/baa example would then trigger a LVM error sort of like “attempt to create new key in locked table”

[1] there are other not nice things about globals, such as he performance hit. But those are, I think, manageable.

[2] this lock would not be a lock in the sense of a data synchronization or mutual exclusion primitive, nor would it be in a security sense. Its goal is for use in eliminating a class of bugs that can be annoying and expensive to find.

That all said, these are all problems with which we have come to understand and live with and have developed various techniques for easing. I have no problems if the PUC-Rio team decide that this is not something that needs changing.

Frank
Luiz Henrique de Figueiredo
2018-07-05 18:01:09 UTC
Permalink
Post by Frank Kastenholz
One could imagine a mechanism where tables get locked - new keys are not allowed to be added to locked tables, but existing keys could be used in the usual way[
Just set a __newindex metamethod for _ENV that raises an error.
Frank Kastenholz
2018-07-05 18:09:11 UTC
Permalink
Problem solved :-)
(I wasn’t sure whether _ENV might be special ... thanks)
Post by Luiz Henrique de Figueiredo
Post by Frank Kastenholz
One could imagine a mechanism where tables get locked - new keys are not allowed to be added to locked tables, but existing keys could be used in the usual way[
Just set a __newindex metamethod for _ENV that raises an error.
Rena
2018-07-05 18:59:21 UTC
Permalink
On Thu, Jul 5, 2018, 14:01 Luiz Henrique de Figueiredo, <
Post by Frank Kastenholz
Post by Frank Kastenholz
One could imagine a mechanism where tables get locked - new keys are not
allowed to be added to locked tables, but existing keys could be used in
the usual way[
Just set a __newindex metamethod for _ENV that raises an error.
+1. IMO Lua's scoping works great as it is. You don't need to do anything
awkward to access globals like `print`, you can have multiple scopes with
`_ENV`, and you can attach metamethods to those scopes (including the
global one) to do clever things like warn/error on unexpected use of
variables. You even can write `_G.x` if you want (or need) to clarify that
you're accessing globals, and it's the same syntax as any other table
access.

Lua's everything-is-a-table design is excellent, and I think people often
don't recognize how powerful it is in its simplicity.
Adin Baber
2018-07-07 03:39:45 UTC
Permalink
Post by Luiz Henrique de Figueiredo
Post by Frank Kastenholz
One could imagine a mechanism where tables get locked - new keys are not allowed to be added to locked tables, but existing keys could be used in the usual way[
Just set a __newindex metamethod for _ENV that raises an error.
+1. IMO Lua's scoping works great as it is. You don't need to do anything awkward to access globals like `print`, you can have multiple scopes with `_ENV`, and you can attach metamethods to those scopes (including the global one) to do clever things like warn/error on unexpected use of variables. You even can write `_G.x` if you want (or need) to clarify that you're accessing globals, and it's the same syntax as any other table access.
Lua's everything-is-a-table design is excellent, and I think people often don't recognize how powerful it is in its simplicity.
I have to agree with Rena here. The simplicity of Lua's table structure is very flexible.


Some other thoughts:

At one point, I made my own strict library. It added a meta-table to _G that would cause an error to be thrown undefined variable was written or read. So, now I had to explicitly mark a variable as global like this:

__global(“variablename”, value) — essentially the same as _G.variablename = value
or
__global(“variablename”) — essentially the same as _G.variablename = nil

The second version was still required to even read a nil value.

However, once the variable existed as a global, you could read and write to it as much as you wanted. It caught the typos, but I really did not like the fact that I had to put the variable names in quotes and thus break standard syntax. So I stopped that.

What I ended up doing was checking for globals in my unit tests. My unit testing structure allows me to define a table that is passed into _ENV when the target file is tested. This table will have any globals I want to use in it, and it will be made strict such that no new globals made be read from or written to it. If I use an unexpected global during a unit test of that file, the test will fail. If I list a global to be used in the tests, and it is not used, the I will be informed of its non-use after the file is done being tested.

What this gives to me:
1) I have an list of all globals that are used.
2) I can use that list to localize all of the globals the file uses at the top of the file, and thus localize them
e.g.
local pairs = pairs
local print = print

This latter feature has been one I have found particularly useful. The minor reason is that all globals are localized, and thus make the code more efficient. The major advantage is that since all the globals are localized, I don’t have to worry about another library doing something silly like redefining how pairs and ipairs work. This compartmentalizes the code quite nicely, and thus makes it much more reliable.

I anyone is interested, I can share some sample code.

***@gmail.com
steve donovan
2018-07-08 10:14:20 UTC
Permalink
Post by Rena
+1. IMO Lua's scoping works great as it is. You don't need to do anything
awkward to access globals like `print`,
Plus, not difficult to write static analyzers that get pedantic about
_unknown_ global access. Saved me much grief.

The one approach I followed was the old 'analyze byte code one'. So
standing on the shoulders of some giants, I did lglob.

I hesitate to use the word 'evil' in the context of programming
language features (except possibly overeager and confusing
auto-conversions that made VB such a mess and continue to vex the
modern Javascript world). If features can be tamed, then they are not
evil.
Sol Salpagarov
2018-07-05 14:53:28 UTC
Permalink
Post by Dirk Laurie
(a) the status quo is bad;
Yes. I prefer "local-by-default for all within chunk".
Post by Dirk Laurie
(b) we need a way to specify whether a variable is global;
Yes. For example, by "global" keyword. Instead a current "local".
Post by Dirk Laurie
(c) one such way is to put a dollar sign in front of the name.
No! Please!! it's extremely bad!!!
Gregg Reynolds
2018-07-05 19:15:02 UTC
Permalink
Post by Dirk Laurie
Post by Viacheslav Usov
Post by Marc Balmer
How was I unclear or neutral when I wrote "It's a bad idea?".
That was not in response to "is this a problem worth solving",
So the OP's diatribe against globals is to be split in three parts,
each requiring that its predecessor is taken for granted.
(a) the status quo is bad;
Status quo is neither good nor bad. It's just the Way Things Are.

(b) we need a way to specify whether a variable is global;
We already have that. Lua is well-defined.

(c) one such way is to put a dollar sign in front of the name.
Meaning, define a new language.

One of the great things about Lua is that it provokes these kinds of fun
debates about language design. I don't see much of that elsewhere but in
the end I think it's productive.

G
Dirk Laurie
2018-07-05 19:39:25 UTC
Permalink
Post by Gregg Reynolds
One of the great things about Lua is that it provokes these kinds of fun
debates about language design. I don't see much of that elsewhere but in the
end I think it's productive.
What makes it fun is that we can argue castles into the air, secure in
the knowledge that the Lua team won't do anything silly.
Gregg Reynolds
2018-07-05 19:41:46 UTC
Permalink
Post by Dirk Laurie
Post by Gregg Reynolds
One of the great things about Lua is that it provokes these kinds of fun
debates about language design. I don't see much of that elsewhere but in
the
Post by Gregg Reynolds
end I think it's productive.
What makes it fun is that we can argue castles into the air, secure in
the knowledge that the Lua team won't do anything silly.
+100. Gobbless the Lua maintainers!
Italo Maia
2018-07-05 20:46:32 UTC
Permalink
Post by Dirk Laurie
Post by Gregg Reynolds
One of the great things about Lua is that it provokes these kinds of fun
debates about language design. I don't see much of that elsewhere but in
the
Post by Gregg Reynolds
end I think it's productive.
What makes it fun is that we can argue castles into the air, secure in
the knowledge that the Lua team won't do anything silly.
That is so true! It is really nice to see that the language is not getting
more complex just because some idea from "x" was presented with enough
sugar coating.
Things need a really good reason to enter core. There are some popular
languages out there adding new "features" without a real need or just
copying features from other languages in a rush, "just because". It is also
nice to see the community standing up for many of the good lua
design choices, even if they are not popular with the cool kids.
Post by Dirk Laurie
Post by Gregg Reynolds
One of the great things about Lua is that it provokes these kinds of fun
debates about language design. I don't see much of that elsewhere but in
the
Post by Gregg Reynolds
end I think it's productive.
What makes it fun is that we can argue castles into the air, secure in
the knowledge that the Lua team won't do anything silly.
--
"A arrogância é a arma dos fracos."

===========================
Me. Italo Moreira Campelo Maia
Co-fundador do Grupo de Usuários Python do Ceará
Secretário ForHacker (fb.com/ForHackerSpace)
Desenvolvedor Full-Stack, Escritor, Empresário, Visionário
-----------------------------------------------------
Meu Livro <http://bit.ly/flask-amazon>, Site <http://www.italomaia.com/>,
Blog <http://eusouolobomau.blogspot.com/>
===========================
Bennett Todd
2018-07-05 21:54:29 UTC
Permalink
I don't know if it's still true, but at least at one point, it seemed like
every release of lua made it smaller, simpler, faster, _and_ more powerful.
It seems impossible to keep improving on all of those at once, but the lua
team is rather special.
Post by Italo Maia
Post by Gregg Reynolds
One of the great things about Lua is that it provokes these kinds of fun
Post by Gregg Reynolds
debates about language design. I don't see much of that elsewhere but
in the
Post by Gregg Reynolds
end I think it's productive.
What makes it fun is that we can argue castles into the air, secure in
the knowledge that the Lua team won't do anything silly.
That is so true! It is really nice to see that the language is not getting
more complex just because some idea from "x" was presented with enough
sugar coating.
Things need a really good reason to enter core. There are some popular
languages out there adding new "features" without a real need or just
copying features from other languages in a rush, "just because". It is
also nice to see the community standing up for many of the good lua
design choices, even if they are not popular with the cool kids.
Post by Gregg Reynolds
Post by Gregg Reynolds
One of the great things about Lua is that it provokes these kinds of fun
debates about language design. I don't see much of that elsewhere but
in the
Post by Gregg Reynolds
end I think it's productive.
What makes it fun is that we can argue castles into the air, secure in
the knowledge that the Lua team won't do anything silly.
--
"A arrogância é a arma dos fracos."
===========================
Me. Italo Moreira Campelo Maia
Co-fundador do Grupo de Usuários Python do Ceará
Secretário ForHacker (fb.com/ForHackerSpace)
Desenvolvedor Full-Stack, Escritor, Empresário, Visionário
-----------------------------------------------------
Meu Livro <http://bit.ly/flask-amazon>, Site <http://www.italomaia.com/>,
Blog <http://eusouolobomau.blogspot.com/>
===========================
Egor Skriptunoff
2018-07-04 20:09:58 UTC
Permalink
The $ prefix seems, to me, like an ugly wart purely aesthetically
Dollar could not by ugly. It is a money symbol :-)
Or did you mean "$ is ugly because it looks too Perl/PHP-ish"? :-)
6. A new statement is provided to declare globals.
Declaring each used global in special global-declaration-statement is
boring.
When you want to determine whether this variable is global or not, you have
to search for global-declaration-statement that may be located far from the
current line.

On the opposite, when you see "$var", you already know (immediately and
without any efforts) that "var" is global.
So, "$var" notation results in more easily readable code.
Gregg Reynolds
2018-07-04 20:17:42 UTC
Permalink
Post by Egor Skriptunoff
The $ prefix seems, to me, like an ugly wart purely aesthetically
Dollar could not by ugly. It is a money symbol :-)
Or did you mean "$ is ugly because it looks too Perl/PHP-ish"? :-)
6. A new statement is provided to declare globals.
Declaring each used global in special global-declaration-statement is
boring.
When you want to determine whether this variable is global or not, you
have to search for global-declaration-statement that may be located far
from the current line.
On the opposite, when you see "$var", you already know (immediately and
without any efforts) that "var" is global.
So, "$var" notation results in more easily readable code.
So does g_var.

A guess: this will never happen.
Viacheslav Usov
2018-07-04 20:31:59 UTC
Permalink
Post by Egor Skriptunoff
Or did you mean "$ is ugly because it looks too Perl/PHP-ish"? :-)
I am not a believer in Hungarian notation. Making it part of any language
is the silliest thing I could think about. Give me as few restrictions as
possible on identifiers and if I feel I need a naming scheme, I can create
one myself, thank you very much.
Post by Egor Skriptunoff
Declaring each used global in special global-declaration-statement is
boring.

You could substitute 'local' for 'global in your statement, and it would be
equally pointless. What is more, your proposal is squarely about declaring
each and every global. But why should it be easier to declare globals than
locals?

Any code that needs a large number of globals is suspect unless there are
special circumstances warranting that; if that is the case, not local =
implicit.
Post by Egor Skriptunoff
When you want to determine whether this variable is global or not, you
have to search for global-declaration-statement that may be located far
from the current line.

That sounds as if that were something of utmost importance. But, again, why
is that more important than having to decide whether a given local is an
upvalue, or a plain local, or whether it eclipses another local? Also, see
above re naming schemes.

Cheers,
V.
Jakub Jirutka
2018-07-04 20:43:19 UTC
Permalink
Post by Egor Skriptunoff
Post by Egor Skriptunoff
When you want to determine whether this variable is global or not, you
have to search for global-declaration-statement that may be located far
from the current line.
That sounds as if that were something of utmost importance. But, again,
why is that more important than having to decide whether a given local
is an upvalue, or a plain local, or whether it eclipses another local?
Also, see above re naming schemes.
Global may be declare absolutely anywhere - in a different file or even
third-party library. That's the problem, this very wide scope. Plain
local has well defined lexical scope, in the worst case one file.
upvalue is limited just to a function.

If you ignore this very important difference and say that it's the same
issue, then the whole discussion is pointless...

Jakub
Post by Egor Skriptunoff
On Wed, Jul 4, 2018 at 10:10 PM Egor Skriptunoff
Post by Egor Skriptunoff
Or did you mean "$ is ugly because it looks too Perl/PHP-ish"?  :-)
I am not a believer in Hungarian notation. Making it part of any
language is the silliest thing I could think about. Give me as few
restrictions as possible on identifiers and if I feel I need a naming
scheme, I can create one myself, thank you very much. 
Post by Egor Skriptunoff
Declaring each used global in special global-declaration-statement is
boring.
You could substitute 'local' for 'global in your statement, and it would
be equally pointless. What is more, your proposal is squarely about
declaring each and every global. But why should it be easier to declare
globals than locals?
Any code that needs a large number of globals is suspect unless there
are special circumstances warranting that; if that is the case, not
local = implicit.
   
Post by Egor Skriptunoff
When you want to determine whether this variable is global or not, you
have to search for global-declaration-statement that may be located far
from the current line. 
That sounds as if that were something of utmost importance. But, again,
why is that more important than having to decide whether a given local
is an upvalue, or a plain local, or whether it eclipses another local?
Also, see above re naming schemes.
Cheers,
V.
Viacheslav Usov
2018-07-04 20:47:22 UTC
Permalink
Post by Jakub Jirutka
If you ignore this very important difference and say that it's the same
issue, then the whole discussion is pointless...

A little earlier you said that you did not read much of this discussion
anyway. Which has to include what I said earlier. Now you are lecturing me
on trivialities and warning me of a pointless discussion. How ironic.

Cheers,
V.
Jakub Jirutka
2018-07-04 21:16:04 UTC
Permalink
I read about half of it already. I know that you support solving this
issue, just in a different way. But this context does not change the
fact that your argument about difference between global vs. local vs.
upvalue was bad, ignoring very important difference in extent of the
scope. I don't think that it's a triviality. That's why I responded to
it. Maybe I should have avoided that sentence about pointless
discussion, sorry about that.

Jakub
Post by Jakub Jirutka
If you ignore this very important difference and say that it's the
same issue, then the whole discussion is pointless...
A little earlier you said that you did not read much of this discussion
anyway. Which has to include what I said earlier. Now you are lecturing
me on trivialities and warning me of a pointless discussion. How ironic.
Cheers,
V.
Viacheslav Usov
2018-07-04 21:36:41 UTC
Permalink
your argument about difference between global vs. local vs. upvalue was
bad, ignoring very important difference in extent of the scope.

Per my proposal, when globals are declared explicitly, they are declared in
the same chunk with locals and upvalues. The complication that you wrote
about with globals defined in other (third party) files no longer applies
(not accidentally, because dealing with the complication is one of the
objectives). Therefore, seeing what is global, local, or an upvalue, and
what eclipses what, becomes similar in complexity, and I do not think that
globals need a further syntactical feature to make them stand out.

I have also said that it would then be entirely in my power to make them
stand out, if I really want that.

Finally, the syntactical difference proposed by Egor is so incompatible
with existing code that I think this is a non-starter just for that reason
alone. If there is any hope for an improvement in this area, it must be
fully compatible with existing code [1]. This is why I proposed a fully
compatible extension.

Cheers,
V.

[1] http://lua-users.org/lists/lua-l/2010-07/msg00532.html

Subject: Re: Globals (more ruminations)
From: Roberto Ierusalimschy <***@...>
Date: Sun, 18 Jul 2010 11:20:42 -0300

Sure compatibility is very important, but the rule is not only for
compatibility. Most small/simple scripts do not need this extra
complication (think about config files or interactive sessions).

-- Roberto
Alexander Mokrushyn
2018-07-04 20:43:53 UTC
Permalink
Would be nice have conception of namespace. Namespace always global, in
every programming language.

Code can look like:

namespace MyNamespace
a = 1

function fn1()
end
end

and if I load code as package, I can access to "a" or function:

print(MyNamespace.a)
MyNamespace.fn1()
On Wed, Jul 4, 2018 at 10:10 PM Egor Skriptunoff <
Post by Egor Skriptunoff
Or did you mean "$ is ugly because it looks too Perl/PHP-ish"? :-)
I am not a believer in Hungarian notation. Making it part of any language
is the silliest thing I could think about. Give me as few restrictions as
possible on identifiers and if I feel I need a naming scheme, I can create
one myself, thank you very much.
Post by Egor Skriptunoff
Declaring each used global in special global-declaration-statement is
boring.
You could substitute 'local' for 'global in your statement, and it would
be equally pointless. What is more, your proposal is squarely about
declaring each and every global. But why should it be easier to declare
globals than locals?
Any code that needs a large number of globals is suspect unless there are
special circumstances warranting that; if that is the case, not local =
implicit.
Post by Egor Skriptunoff
When you want to determine whether this variable is global or not, you
have to search for global-declaration-statement that may be located far
from the current line.
That sounds as if that were something of utmost importance. But, again,
why is that more important than having to decide whether a given local is
an upvalue, or a plain local, or whether it eclipses another local? Also,
see above re naming schemes.
Cheers,
V.
Luiz Henrique de Figueiredo
2018-07-04 20:56:35 UTC
Permalink
On Wed, Jul 4, 2018 at 5:43 PM, Alexander Mokrushyn
Post by Alexander Mokrushyn
Would be nice have conception of namespace. Namespace always global, in
every programming language.
namespace MyNamespace
a = 1
function fn1()
end
end
print(MyNamespace.a)
MyNamespace.fn1()
You can already do exactly that with _ENV:

MyNamespace = {}
do
_ENV = MyNamespace
...
end
Alexander Mokrushyn
2018-07-04 21:04:52 UTC
Permalink
Yes, only _ENV looks like hardly readable code.

namespace MyNamespace - more clean

and can look even more readable with:

use MyNamespace
print(a)
fn1()


For me _ENV works too, only some time code in Lua looks like regular
expressions, powerful but hard to read :)


On Wed, Jul 4, 2018 at 4:56 PM, Luiz Henrique de Figueiredo <
Post by Luiz Henrique de Figueiredo
On Wed, Jul 4, 2018 at 5:43 PM, Alexander Mokrushyn
Post by Alexander Mokrushyn
Would be nice have conception of namespace. Namespace always global, in
every programming language.
namespace MyNamespace
a = 1
function fn1()
end
end
print(MyNamespace.a)
MyNamespace.fn1()
MyNamespace = {}
do
_ENV = MyNamespace
...
end
Jakub Jirutka
2018-07-04 19:06:47 UTC
Permalink
Hi,

I completely agree with the proposal and all the points why it's needed.
- very well written!

"global by default", specifically defining variable as global by default
(and also no difference between declaring global variable and
reassignment of any variable), is one of the few ugly sides of Lua.
Solving this problem would make Lua much better language.

I have just one concern - backward compatibility with existing Lua
modules. If I as a Lua programmer want to require some possibly outdated
third-party Lua modules, there should be a way how to make it work on
newer Lua with the said feature without modifying the original sources.

There are multiple ways how to achieve that:
- make the new feature *opt-in* per file using some "magic" comment or
string at top of the file,
- make the new feature *opt-out* per file using e.g. extra argument for
the require() function (and lower-level functions for loading chunks as
well)
- make the new feature opt-in or opt-out globally using lua(1) CLI
option or some global variable (this would be probably the easiest one,
but also the one I'd strongly discourage for multiple reasons)
- some different way?

(I didn't read these dozens following messages, so I'm sorry if
repeating what someone else already said.)

Jakub
Post by Egor Skriptunoff
Hi!
Let me start (n+1)-th thread about "global by default" feature of Lua.
 
My suggestion is to replace "global by default" approach with "nothing
 
$print("Hello world")    -- ok
print("Hello world")     -- syntax error: referencing undeclared
variable "print"
_G.print("Hello world")  -- syntax error: referencing undeclared
variable "_G"
 
"$" is not a part of an identifier.
"$" is a lexem (for example, there could be a space between "$" and
global variable name).
"$" is absolutely the same as "_ENV." but is more comfortable to use.
 
Why do we need this?
 
1)
"$globalvar" notation introduces two separate namespaces: one for
globals and one for locals/upvalues.
As a result of this separation, most of variable name typos will be
detected at compile time.
Although global name typos will not be detected ($math.sin ->
$moth.sin), the most of identifiers in properly-written Lua programs are
locals.
Currently, writing Lua programs without "global-nil-alarmer" (such as
"strict.lua") is practically impossible (because typos in local variable
names are silently converted to globals).
 
2)
"$print" contains more symbols than "print", and you have to press SHIFT
on your keyboard to type "$", but this is not a drawback.
Instead, there is a point in it: users would have to pay attention to
slow global access.
More finger moves = more CPU time to access.
So, we are adding "ergonomical motivation" to cache globals in Lua
programs :-)
 
3)
Polluting of global namespace is already discouraged in Lua, so
introducing "$" prefix for globals is the next step in that direction.
It is a polite way to say: "use globals only when they are really needed".
 
4)
The "$globalvar" notation will solve problem with globals occasionally
 
local function sort_desc(table)
   table.sort(table, function(a, b) return a>b end)  -- very popular
newcomers' mistake
end
 
5)
The "$globalvar" notation will make the difference between
"monkey-patch-friendly code" and "monkey-patch-unfriendly code" more
easy to see.
 
 
BTW, "_ENV" could be removed from Lua as "$" could do the same (with
some modifications in the parser to interpret "$" either as "_ENV." or
 
$print()           -- instead of print()
$.print()          -- instead of print()
local env = $      -- instead of local env = _ENV
$[key] = value     -- instead of _ENV[key] = value
function sndbx($)  -- instead of function sndbx(_ENV)
What are your thoughts on this?
-- Egor
Thijs Schreijer
2018-07-04 20:17:47 UTC
Permalink
On 4 Jul 2018, at 21:06, Jakub Jirutka <***@jirutka.cz<mailto:***@jirutka.cz>> wrote:

Hi,

I completely agree with the proposal and all the points why it's needed.
- very well written!

"global by default", specifically defining variable as global by default
(and also no difference between declaring global variable and
reassignment of any variable), is one of the few ugly sides of Lua.
Solving this problem would make Lua much better language.


Usually stuff is the way it is for a reason. And complex problems don’t have simple solutions.

As I learned, reading back some previous answers by Roberto [1] on this matter, "global by default” is actually the more common pattern.

Thijs


[1] http://lua-users.org/cgi-bin/namazu.cgi?query=global+by+default+%2Bfrom%3Aroberto%40&idxname=lua-l&max=20&result=normal&sort=score<http://lua-users.org/cgi-bin/namazu.cgi?query=global+by+default++from:roberto@&idxname=lua-l&max=20&result=normal&sort=score>
If you’re really interested in the subject and the why, I highly recommend reading some of those messages.
Viacheslav Usov
2018-07-04 20:43:09 UTC
Permalink
[1]
http://lua-users.org/cgi-bin/namazu.cgi?query=global+by+default+%2Bfrom%3Aroberto%40&idxname=lua-l&max=20&result=normal&sort=score
<http://lua-users.org/cgi-bin/namazu.cgi?query=global+by+default++from:roberto@&idxname=lua-l&max=20&result=normal&sort=score>

I get no results at that URL. Could you reference some messages directly?

Cheers,
V.
Gregg Reynolds
2018-07-04 20:44:46 UTC
Permalink
Post by Thijs Schreijer
[1]
http://lua-users.org/cgi-bin/namazu.cgi?query=global+by+default+%2Bfrom%3Aroberto%40&idxname=lua-l&max=20&result=normal&sort=score
"No document matching your query."
Thijs Schreijer
2018-07-04 21:15:35 UTC
Permalink
On 4 Jul 2018, at 22:44, Gregg Reynolds <***@mobileink.com<mailto:***@mobileink.com>> wrote:



On Wed, Jul 4, 2018, 3:18 PM Thijs Schreijer <***@thijsschreijer.nl<mailto:***@thijsschreijer.nl>> wrote:


[1] http://lua-users.org/cgi-bin/namazu.cgi?query=global+by+default+%2Bfrom%3Aroberto%40&idxname=lua-l&max=20&result=normal&sort=score<http://lua-users.org/cgi-bin/namazu.cgi?query=global+by+default++from:roberto@&idxname=lua-l&max=20&result=normal&sort=score>

"No document matching your query."



Odd, I also get that. Query the archive for “global by default +from:roberto@“

Thijs
Gregg Reynolds
2018-07-04 20:39:59 UTC
Permalink
Post by Egor Skriptunoff
Hi!
Let me start (n+1)-th thread about "global by default" feature of Lua.
My suggestion is to replace "global by default" approach with "nothing by
Its one thing to introduce a new special symbol that does not change
existing semantics. It's a whole 'nother thing to "replace" existing
semantics. You could add $ with special meaning, but then all you've done
is clutter the language. If you also "replace" existing semantics, e.g. by
changing global-by-default, then you have by definition defined a new
language, which is not Lua.

This is a very bad idea. Global-by-default is a fact of life in Lua, and it
will never change (I hope). You deal it with by practicing disciplined
programming.
Jakub Jirutka
2018-07-04 20:58:02 UTC
Permalink
Post by Gregg Reynolds
This is a very bad idea. Global-by-default is a fact of life in Lua, and
it will never change (I hope). You deal it with by practicing
disciplined programming.
This is not a very useful advice when you deal with code written by
someone else. Global as default and similar things are *obviously* no
such big deal when you live in a vacuum and don't deal with other's
people code. Then you have to just apply good discipline and you're safe.

Unfortunately, based on some replies in this ML, it looks like many
people really don't understand problems that appear only when you have
experience from working with someone else's code, trying to understand
it, debug it or refactor...

Jakub
Post by Gregg Reynolds
On Wed, Jul 4, 2018, 12:26 AM Egor Skriptunoff
Hi!
Let me start (n+1)-th thread about "global by default" feature of Lua.
 
My suggestion is to replace "global by default" approach with
"nothing by default" by introducing special syntax for accessing
Its one thing to introduce a new special symbol that does not change
existing semantics. It's a whole 'nother thing to "replace" existing
semantics. You could add $ with special meaning, but then all you've
done is clutter the language. If you also "replace" existing semantics,
e.g. by changing global-by-default, then you have by definition defined
a new language, which is not Lua.
This is a very bad idea. Global-by-default is a fact of life in Lua, and
it will never change (I hope). You deal it with by practicing
disciplined programming.
Gregg Reynolds
2018-07-04 21:07:12 UTC
Permalink
Post by Jakub Jirutka
Post by Gregg Reynolds
This is a very bad idea. Global-by-default is a fact of life in Lua, and
it will never change (I hope). You deal it with by practicing
disciplined programming.
This is not a very useful advice when you deal with code written by
someone else. Global as default and similar things are *obviously* no
such big deal when you live in a vacuum and don't deal with other's
people code. Then you have to just apply good discipline and you're safe.
Unfortunately, based on some replies in this ML, it looks like many
people really don't understand problems that appear only when you have
experience from working with someone else's code, trying to understand
it, debug it or refactor...
Shrug. Fact of life with Lua. I don't think anybody is claiming this is not
a problem. Just that it cannot be addressed in the manner proposed. You
can't expect the language to protect you from badly written libs.

In any case, my guess is that the chances of Egor's proposal being adopted
is somewhere in the vicinity of zero, so we're just having fun.
Dirk Laurie
2018-07-04 21:21:56 UTC
Permalink
Post by Jakub Jirutka
Unfortunately, based on some replies in this ML, it looks like many
people really don't understand problems that appear only when you have
experience from working with someone else's code, trying to understand
it, debug it or refactor...
I have substantial experience of that. For the first five years of my career,
I modified other people's Fortran 66 programs.

I had a boss who taught me that a specification without code is much better
than code without a specification, because you could always write a
program to match the specs but you could not guess what a badly written
program was supposed to do.

There was no such thing as an undefined name.

Global variables were achieved by COMMON statements. You simply
copied twenty lines of unreadable declarations to the top of every
subroutine, whether it used one or fifty of those names. Or none.

A typo in the name of a variable was by far the easiest mistake to find.
Following logic through goto statements, that was much harder.

What I learnt was that understanding and debugging someone else's
code is a PITA in any language, period. No amount of dollar signs on
global variables is going to change that.
Pierre Chapuis
2018-07-05 12:42:37 UTC
Permalink
Post by Jakub Jirutka
This is not a very useful advice when you deal with code written by
someone else. Global as default and similar things are *obviously* no
such big deal when you live in a vacuum and don't deal with other's
people code. Then you have to just apply good discipline and you're safe.
Unfortunately, based on some replies in this ML, it looks like many
people really don't understand problems that appear only when you have
experience from working with someone else's code, trying to understand
it, debug it or refactor...
Several posters here seem to be under that impression, so let me clarify. I made a presentation [1] which talked about that at Lua Workshop 2013. As you can see from the slides about "quality", I am aware of the problem. I still don't think this proposal is a good idea.

There are three main kinds of code in Lua: module code, application code and "scripting" code (configuration, etc). They have different requirements.

If someone writes a module (in Lua) that writes to the global namespace, you can easily detect it with existing tools and report it to them. If they don't fix it, you should consider why you are depending on poorly maintained modules. For what it's worth, I am maintaining a growing production code base of Lua code, and our build step fails unless luacheck passes on *all* the Lua code we ship, including dependencies (we do have selected exceptions in .luacheckrc).

If you use Lua as a scripting language and want to disallow globals in code written by users of your application, you can. Just sandbox them, and if you really want them to use locals only, set a metatable on their _ENV and make it read-only.

[1] http://files.catwell.info/presentations/2013-11-lua-workshop-lua-ecosystem/
Duane Leslie
2018-07-04 23:16:45 UTC
Permalink
Post by Egor Skriptunoff
local _G = _G; local _ENV = nil
and then use e.g. `_G.print
local next, io, print = next, io, print
-- etc: first cache all the globals you need
local _ENV = setmetatable({},{__index=error, __newindex=error})
These are two more "yet another run-time alarmers".
They are not equivalent to my suggestion.
Any "runtime-alarmer" is unable to find all local variable name typos (for example, inside currently inactive "if" branch).
...
All existing solutions are actually run-time checkers, they are unable to solve the problem.
And simultaneously I want to solve another problem "globals are accidentally shaded out by locals with the same name".
Already solved. See http://lua-users.org/lists/lua-l/2016-05/msg00187.html , also the discussion over the previous week.

This doesn't work in global scope, only in function scope, but it allows you to control the accessibility of globals *and* upvalues (which has largely been missing from this discussion) and generates compile time errors if an unknown variable is accessed. The syntax can only work at a scope change because of the way the compiler works, so in some cases you may need an extra closure to get the behaviour you want.

I've been running this in all of my Lua code for 2 1/2 years now.

Regards,

Duane.
Egor Skriptunoff
2018-10-26 21:03:36 UTC
Permalink
Hi Egor,
sorry for sending this directly to you but I'm no longer subscribed to
lua-l
and can't post it there.
Post by Egor Skriptunoff
My suggestion is to replace "global by default" approach with "nothing by
Browsing through the pile-up of lua-l mails I found your article and just
want to let you know that, contrary to most of the negativ replies, I
totally
agree with your proposal. So much that I once (in 2013, for Lua 5.2) even
did a patch that implements it ;-)
I had one difference though: the parser starts in regular lua mode and only
if it detects the first $-sign it switches to "explicit globals" mode for
that chunk. That way it was 100% backwards compatible.
Ciao, ET.
Thanks, Edgar.
I like it too - when a new feature is simultaneously useful and 100%
backwards compatible.
So, you've made a patch for parsing $-globals 5 years ago?
Nice!

Loading...