RE: Namespace improvement ?

new topic     » topic index » view thread      » older message » newer message

Christian Cuvier wrote:
> 
> 
> > Matt Lewis wrote:
> > 
> >>> Yes, please elaborate.  I recall you mentioning that you'd dropped the 
> >>> namespace thing, but I don't recall any negative aspects being in there,
> >>> other than the time it would take:
> > 
> > 
> > It was months ago, so I don't remember all the details, but
> > I think there were basically two negatives that started
> > to loom larger in my mind:
> > 
> >    1. The change was going to add complexity and subtlety to
> >       namespace rules that many people already had trouble
> >       remembering.
> > 
> >    2. After porting thousands of lines of C code to Euphoria 
> >       (i.e. the front-end), I had a couple of nasty cases where I 
> >       accidentally declared a global variable in two different files.
> >       No error message was given, yet I was updating two different
> >       variables, not one. It took a while to figure out what was 
> >       happening. Since the proposed change to the namespace rules
> >       would increase the chances of this sort of bug going
> >       undetected, I considered that to be a negative thing,
> >       that would partially offset the positive effect of fewer 
> >       spurious error reports.
> > 
> > Regards,
> >    Rob Craig
> >    Rapid Deployment Software
> >    http://www.RapidEuphoria.com
> 
> An easy and cleaner way aroubnd this would be to implement 
> promoting/demoting 
> of a global identifier.
> 
> Assume my_global is defined in libs A2 and B2. Library A1 includes A2, 
> B1 
> includes B2. As long as you don't include A1 and B1 together, no 
> problem.
> 
> Now if program P includes both A1 and B1, a nama clash occurs on the 
> first 
> invocation of my_global in any of the five involved files. An easy way 
> for the 
> author of P to avoid this, while still relying on the UNMODIFIED A* and 
> B* 
> (this reduces package sizes, negates compatibility issues etc, this is 
> why 
> IK's way out by symbol renaming is not usable) could be to do this:
> 
> }}}
<eucode>
> include A1 as a1
> demote my_global from a1
> include B1 as b1
> </eucode>
{{{

> 
> The middle line would prevent unqualified accass to a1:my_global. 
> Additionally:
> - P can still access a1:my_global as appropriate using the explicit 
> namespace;
> - A1 and B1 are no longer affected, as their symbol tables are not 
> affected by 
> the demote command from P;
> - If, at some point, P finds it more convenient to access b1:my_global 
> without 
> the b1:, it still can by issuing:
> 
> }}}
<eucode>
> demote my_global from b1
> promote my_global from a1
> </eucode>
{{{

> 
> promote would just undo demote's effect.
> - P doesn't need to know how A1 includes A2, or any detail of this kind. 
> It 
> just has to know that A1 knows about a global called my_global.
> 
> This implies that every file has the following symbol tables:
> - local identifiers
> - global identifiers from directly included files (these tables would be 
> 
> inherited)
> - the default (unqualified) namespace, where symbol visibility could be 
> adjusted.
> 
> The bottom line is:
> - A file always can see globals from files it includes, files the latter 
> files 
> include and so on;
> - A file can see any global unqualified symbol if this symbol was not 
> demoted;
> - A file cansee any global by using the appropriate namespace qualifier;
> - demote is reversed by promote and vice versa.
> 
> Is this confusing?
> Would it break any code?
> 
> I'll consider implementing it in the 2.5 source, as no mod to the IL 
> appears 
> to be necessary. promote and demote are just directives targetting the 
> parser, 
> and are not supposed to generate any code. The only issue is adding an 
> intermediate layer of symbol tables between local and global tables, one 
> 
> intermediate table for each file.
> 
> No timetable for this though, as I don't have much free time and I'd 
> like to 
> release Syntax2 for xControls - way to go still.
> 
> CChris
> 
> 

The attraction of Euphoria is it's simplicity, and it's powerful use of 
the few existing concepts that are available.

I think there is a good solution the the namespacing problem, but it 
requires breaking backwards compatability. IMO for this change, it would 
be worth breaking from the mould...

My suggestion is that the scope of an include file should only extend to 
the caller. IOW an included file should be local to the file that 
includes it, instead of global. This would make an included file part of 
the same local scope as the calling file. If you want to allow an 
include file to be accessed by 3rd-party files (B includes A, C includes 
B), you include the first file as global.

Ex1.
-- fileB.e --
include fileA.e <-- fileB can access any globals in fileA.e
                <-- (locally included)
-- fileC.e --
include fileB.e <-- fileC cannot access fileA,
                <-- because fileA was not included globally.

Ex2.
-- fileB.e --
global include fileA.e <-- fileB.e and any files that include it,
                       <-- can access any globals in fileA.e
                       <-- (globally included)
-- fileC.e --
include fileB.e  <-- fileA.e is included globally in fileB.e,
                 <-- so fileC.e can access the identifiers in fileA.e
-- fileD.e --
include fileC.e  <-- fileD.e cannot access any identifiers declared 
                 <-- in fileB.e or any files it includes, because
                 <-- fileB.e was not included globally in fileC.e

Notice, that there is no new concepts introduced whatsoever.
The solution elegantly takes advantage of the existing concept of global 
scope and extends it to apply to included files.
It's graceful, intuitive and actually brings includes into a common 
concept of scoping rules, just like any other identifier. The only 
drawback is that it breaks compatability, which I don't think is a big 
deal, weighed against the advantage of a better include system.

Why do I think the include system needs to be changed, and why does it 
affect namespacing?
It should be changed because, a great majority of the time, when a 
programmer includes a file, it is used only internally within their 
project. Currently, we have to resort to creating lengthly and obscured 
global identifiers, so that internal files can interface with eachother, 
meanwhile, all those globals are exposed to the whole of the 
application, not just the part that require it.
It affects namespacing, because as I said, currently we must contaminate 
the global namespace, in order to interface between internal libs. This 
is the most profound impact on 'global pollution'. If we can address 
that issue, we have solved 80% of the namespace problem.

With an include system like I described, I think that the need for 
namespacing could be virtually eliminated.

To address the namespacing issue directly, I propose an 'alias' keyword.
Alias would allow the programmer to specifiy exactly which identifier 
they want to refer to and make a shortcut method of identifying it.

Eg
include fileA.e as fileA
include fileB.e ad fileB
alias fooA = fileA:foo, fooB = fileB:foo

This would solve any indiscrepencies, as the programmer would have full 
control of what they want to refer to, without having to resort to using 
qualifiers throughout their code.

Chris Bensler
Code is Alchemy

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu