lua-users home
lua-l archive

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


I`m replying to the list before this turns into a major "war" about
taste in language design.

>From rw20@cornell.edu Thu Dec 11 10:52:12 1997

>Since my last posting about locals I've spent a 
>fair amount of time thinking about the issue.  I still
>think defaulting to global access is a real problem for me.

Of course, the easy answer here is:
	"if it's a real problem for you, do not use Lua." :-)
However, I'm not looking for easy answers here.

Making all variables global by default was a decision taken in the very early
days of the design.
The rationale is that Lua is designed to be used as a configuration language,
where end users will hardly ever write their own functions.
Now imagine the mess of having to write

	global fgcolor="red"
	global bgcolor="white"
	global tolerance=0.001

This seems quite verbose and useless, from the point of view of the end user.
So the decision of having globals by default makes sense to us ;-) and
we don't feel we need to change it.
Moreover, we cannot change it without breaking *lots* of Lua code.

>While explaining Lua to some folks for whom I wrote 
>a little preprocessor using Lua, I realized that explaining
>and supporting the global default model to semi-technical
>users is not ideal.

Really? Do semi-technical users prefer/understand local variables??

>To clarify, my basic problem is that default global 
>access easily turns typo-bugs into really difficult
>ones (that can be extremely execution order dependant).

I admit that typos can created subtle bugs.
After all, experts need to write Lua code to be used by end users,
and the experts need ways to write safe code.

Now, name clash is not a problem with Lua as a language, but rather with how
it is used.
Name clash occurs in C too.
Try defining your own malloc with a different semantics and see what happens.
Try #including <math.h> and have global variables called y0,y1,yn,gamma.

Having said this, Lua does provide ways to cope with name clashes, if this
is a problem for you. Just don't expect this to be as easy as a 'global'
keyword in front of everything. Experts pay a price for their expersise
(and they can charge too!).
This is Lua's philosophy of being simple while being extensible.
In this case, the simplest thing is to make everything global.
But Lua is extensible and allows you to change this simple default if needed.
You just have to write some (maybe subtle) code for this.

The FAQ describes one way to avoid name clashes, which I'll expand below.

>Yesterday, I sat down to work with setting up tag methods 
>to at least deliver runtime warnings.  My idea was to make 
>it illegal to access globals unless their name started with 
>'g' and the second letter was a capital.

You're right, that's a perfect application for tag methods!

>As some of you 
>probably know, I found that you can't set the get and set
>global methods for some built-in types.

Right. This is because strings and numbers are not objects but just values.
Consider the code below:

	a=1	b=a
	c={}	d=c

a and b have the same value but the two '1' are "different".
if you now do a=2 then b is still 1.
c and d have the same value and it it's shared.
if we now do d.x=1 then c.x will be 1.
so, tag methods can be set for table values but not for numbers or strings.

>Looking at the 
>C source code this seems to be prevented by a valid_events
>table.
>Can I change that table and get access to those tags?

Sure, you can do that in your copy of Lua. (But don't redistribute!)
But I think you'll get into a mess, as described above.

The solution for this is never to store simple values in global variables,
but rather acces them through a table (for which you *can* set tag methods).
The FAQ describes a similar solution for creating read-only variables.

So, to implement your idea of only having globals named g[A-Z]..., you could:
(CAUTION: untested code ahead)

0. create a tag for tables representing globals:
	gGtag=newtag()
	
1. set the 'get/setglobal' tag methods for the nil tag to create a table
   with tag gTag with a single field value containing the actual value:

   function gGsetglobal0(x,v)
	if badname(x) then error("`"..x.."' not a global variable") end
	local t={value=v}
	settag(t,gGtag)
	return t
   end

   function gGgetglobal0(x)
	if badname(x) then error("`"..x.."' not a global variable") end
	return nil
   end

   settagmethod(tag(nil),"setglobal",gGsetglobal0)
   settagmethod(tag(nil),"getglobal",gGgetglobal0)

   This will catch all accesses to undefined variables and only allow
   "good" names to be used as global variables.

2. set the 'get/setglobal' tag methods for good names:

   function gGsetglobal(x,old,new)
	old.value=new
	return new
   end

   function gGgetglobal(x,v)
	return v.value
   end

   settagmethod(gGtag,"setglobal",gGsetglobal)
   settagmethod(gGtag,"getglobal",gGgetglobal)

I hope this is clear and works for you.

>Does anyone agree that this is a problem?  If everyone 
>else is happy with global access, please excuse my 
>persistance.

I'm interested in what other people think about this "problem".
--lhf