Say No to global-by-default

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
91 messages Options
12345
Reply | Threaded
Open this post in threaded view
|

Say No to global-by-default

Egor Skriptunoff-2
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
Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Steven K.
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.

Egor Skriptunoff <[hidden email]> schrieb am Mi., 4. Juli 2018 07:26:
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
Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Daurnimator
In reply to this post by Egor Skriptunoff-2
On 4 July 2018 at 15:26, Egor Skriptunoff <[hidden email]> wrote:

> 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

  - 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"?)

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Russell Haley
In reply to this post by Egor Skriptunoff-2


On Tue, Jul 3, 2018 at 10:26 PM, Egor Skriptunoff <[hidden email]> wrote:
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?

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


-- Egor

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Egor Skriptunoff-2
In reply to this post by Steven K.
On Wed, Jul 4, 2018 at 8:39 AM, Steven K. wrote:

"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?

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Steven K.
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".

2018-07-04 8:04 GMT+02:00 Egor Skriptunoff <[hidden email]>:
On Wed, Jul 4, 2018 at 8:39 AM, Steven K. wrote:

"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?


Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Sean Conner
In reply to this post by Egor Skriptunoff-2
It was thus said that the Great Egor Skriptunoff once stated:

> On Wed, Jul 4, 2018 at 8:39 AM, Steven K. wrote:
>
> >
> > "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

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Axel Kittenberger
In reply to this 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.

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Marc Balmer
In reply to this post by Egor Skriptunoff-2


Am 04.07.2018 um 07:26 schrieb Egor Skriptunoff <[hidden email]>:

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?

It's a bad idea.  Very bad.


-- Egor

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Pierre-Yves Gérardy
In reply to this post by Egor Skriptunoff-2
On Wed, Jul 4, 2018 at 7:26 AM, Egor Skriptunoff
<[hidden email]> wrote:
> "$" 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

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Sean Conner
In reply to this post by Axel Kittenberger
It was thus said that the Great Axel Kittenberger once stated:
>
> 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

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Sean Conner
In reply to this post by Pierre-Yves Gérardy
It was thus said that the Great Pierre-Yves Gérardy once stated:

> On Wed, Jul 4, 2018 at 7:26 AM, Egor Skriptunoff
> <[hidden email]> wrote:
> > "$" 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.

  Nope.  If I want to program in Perl (or Ruby for that matter), I know
where to find it.

  -spc


Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Petri Häkkinen
In reply to this post by Marc Balmer
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
Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Pierre Chapuis
In reply to this post by Egor Skriptunoff-2
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...

On Wed, Jul 4, 2018, at 07:26, Egor Skriptunoff wrote:
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

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Pierre Chapuis
In reply to this post by Egor Skriptunoff-2
> ”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.

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Viacheslav Usov
In reply to this post by Egor Skriptunoff-2
On Wed, Jul 4, 2018 at 7:26 AM Egor Skriptunoff <[hidden email]> wrote:

> 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.
Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Etiene Dalcol
> 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


On 4 July 2018 at 10:28, Viacheslav Usov <[hidden email]> wrote:
On Wed, Jul 4, 2018 at 7:26 AM Egor Skriptunoff <[hidden email]> wrote:

> 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

Software Engineer and NLP Researcher
Lua Space http://lua.space
LuaConf http://luaconf.com

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Viacheslav Usov
On Wed, Jul 4, 2018 at 12:02 PM Etiene Dalcol <[hidden email]> wrote:
> 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.

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Dirk Laurie-2
In reply to this post by Steven K.
2018-07-04 7:39 GMT+02:00 Steven K. <[hidden email]>:

> "global-by-default" is evil, no more to say.

I am nevertheless going to say something.

> 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.

Reply | Threaded
Open this post in threaded view
|

Re: Say No to global-by-default

Soni "They/Them" L.
In reply to this post by Viacheslav Usov


On 2018-07-04 07:18 AM, Viacheslav Usov wrote:

> On Wed, Jul 4, 2018 at 12:02 PM Etiene Dalcol <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     > 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.

12345