1. Namespace clobbering internals

I create a db.e file that defines the word close. I then:

include db.e as d

--- do things
f = open(filename, "w")

-- later
close(f)


It called the database's close function, not the internal. So, even if you use a
namespace, your included files cannot define functions by the same name as an
internal and you expect to continue to use an internal function?

--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » topic index » view message » categorize

2. Re: Namespace clobbering internals

Jeremy Cowgar wrote:
> 
> I create a db.e file that defines the word close. I then:
> 
> }}}
<eucode>
> include db.e as d
> 
> --- do things
> f = open(filename, "w")
> 
> -- later
> close(f)
> </eucode>
{{{

> 
> It called the database's close function, not the internal. So, even if you use
> a namespace, your included files cannot define functions by the same name as
> an internal and you expect to continue to use an internal function?
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

Jeremy,

As far as I can tell, builtin routines are automatically in a global namespace.
Anything that goes there is immediately available to every bit of the rest of
the
program being parsed. At the end of parsing that namespace must be chock full.

A program may define a routine with the same name as that of a builtin. If the
routine
is also specified as 'global' it will replace the original one and so we end up
with
the problem you encountered here.

I solve this in orac in 2 ways:

1) Anything defined as 'global' will only reach to the next level and cannot
exceed that range unless propagated further. If there could be said to be global
namespace in Orac, it is superbly clean.

2) Use the prefix 'builtin' and the compiler will know that you only refer to
the builtin symbol.

In the code fragment above, the only change Orac needs for it to work correctly
is to drop the "as d" part. Your global "close" will override the builtin
"close"
until the end of that file, at which, time the builtin "close" will reassert
itself.

If you ever needed to access the builtin "close" inside that file then it is
just a case of..

builtin: close()

Well, I'm not sure that this actually helps you unless you convert to Orac
(Welcome to the Dark Side, brother, hehehe...).
No, seriously, since you've got work to do NOW, what I would do is just use
my_close.

regards,
Mike

new topic     » goto parent     » topic index » view message » categorize

3. Re: Namespace clobbering internals

Would it make sense that if a function/variable is called with no namespace
qualifier that exists as a built-in and user defined inside a namespace that the
built-in be used? That would seem like the logical answer.

The user knew there would be a conflict, thus, he/she included the file w/the
conflict with a namespace to prevent that conflict.

Now. If you include a file w/no namespace and now you have a built-in and user
defined function of the same name, no namespace qualifier and called it with no
namespace qualifier, then I would think the application should err out as it does
now.

Matt, what do you think?

include pgsql.e as db

db:close() --- we know it's calling pgsql.e's close function

f = open(...)
close(f)  --- no namespace given, use the built-in


... another example

include pgsql.e

close() 
--- hm, Euphoria cannot tell if they want built-in 
--- or pgsql.e's close(), therefore crash Euphoria with
--- the namespace qualifier error it currently uses


--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » goto parent     » topic index » view message » categorize

4. Re: Namespace clobbering internals

Jeremy Cowgar wrote:
> 
> It called the database's close function, not the internal. So, even if you
> use a namespace, your included files cannot define functions by the same
> name as an internal and you expect to continue to use an internal function?

Yes, euphoria namespaces work differently than in, say, C++.  They don't 
hide anything, they just serve to disambiguate.

Matt

new topic     » goto parent     » topic index » view message » categorize

5. Re: Namespace clobbering internals

Jeremy Cowgar wrote:
> 
> Would it make sense that if a function/variable is called with no namespace
> qualifier that exists as a built-in and user defined inside a namespace
> that the built-in be used? That would seem like the logical answer.
> 
> The user knew there would be a conflict, thus, he/she included the file
> w/the conflict with a namespace to prevent that conflict.
> 
> Now. If you include a file w/no namespace and now you have a built-in and
> user defined function of the same name, no namespace qualifier and called
> it with no namespace qualifier, then I would think the application should
> err out as it does now.

This will break code.  One of my favorite things to do is to overload things
like print.  Of course, that could be fixed by using namespaces, but it
sort of defeats the purpose of overriding something like this.  It can
make debugging easier by inserting an override that logs, or does something
different, or whatever.

Also, what if you want to use the overload in the same file as it is
declared?  I suppose you could have the file include itself, but as CChris
would certainly tell us, that would just be silly.  A better solution might
 be to reserve a namespace for built-ins.  Maybe something like, "eu".

So your example might become:
include pgsql.e as pg
  include mysql.e as my
  pg:close()    -- pgsql.e's close function
  my:close()    -- mysql.e's close function
  eu:close()    -- reserved built-in namespace, use the built-in
  close()       -- error, multiple definitions

Matt

new topic     » goto parent     » topic index » view message » categorize

6. Re: Namespace clobbering internals

Matt Lewis wrote:
> 
> A better solution might
>  be to reserve a namespace for built-ins.  Maybe something like, "eu".
> 
> So your example might become:
> }}}
<eucode>
>   include pgsql.e as pg
>   include mysql.e as my
>   pg:close()    -- pgsql.e's close function
>   my:close()    -- mysql.e's close function
>   eu:close()    -- reserved built-in namespace, use the built-in
>   close()       -- error, multiple definitions
> </eucode>
{{{


Yes, that's a good solution. I tried to follow the internals about how
namespaces work and have failed to have it click yet. Can we make this change?
All internals have a reserved namespace, eu, that can optionally be used if the
programmer sees the need.

As you pointed about about my solution, it will break code and take away some of
the benefit, but adding a namespace to internals should not break anything and
only solve problems.

What would it take to do this? If you want to do it, or maybe give me a few
pointers then I can play with doing it. Your call.

--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » goto parent     » topic index » view message » categorize

7. Re: Namespace clobbering internals

This is what I tried to explain in the chat room.  We would like to put
included modules into a namespace exclusively so that a function such as
close could ONLY be referenced through its name space: d:close() but not
close().  You see when functions are included by namespace you set a name
for they also go into a global local namespace.

Right now:
include db.e -- includes into the global name space

include db.e as d -- includes into global namespace and namespace 'd'.

-- no way to put include db.e into a namespace 'd' exclusively.


Perhaps you could use existing keywords in a new way:

include db.e as d, without global
-- includes db.e into d but close() will call the builtin.  
-- Even if there is a function called insert in db.e, calling insert() will
fail,
-- you must type d:insert().

Jeremy Cowgar wrote:
> 
> I create a db.e file that defines the word close. I then:
> 
> }}}
<eucode>
> include db.e as d
> 
> --- do things
> f = open(filename, "w")
> 
> -- later
> close(f)
> </eucode>
{{{

> 
> It called the database's close function, not the internal. So, even if you use
> a namespace, your included files cannot define functions by the same name as
> an internal and you expect to continue to use an internal function?
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

new topic     » goto parent     » topic index » view message » categorize

8. Re: Namespace clobbering internals

"include db.e as d, without global"
in a module looks more like a syntax to prevent a program which called 
this module from receiving db.e, rather than this module not receiving 
it without its namespace; an option I would like to see, incidentally.

Perhaps:
 "include db.e as d only"
might be sufficient.

However, Jeremy Cowgar's suggestion of a standard namespace such as eu 
for builtin routines is equally good.

Arthur Crump, in Cheshire, England.

Shawn Pringle wrote:
> 
> This is what I tried to explain in the chat room.  We would like to put
> included modules into a namespace exclusively so that a function such as
> close could ONLY be referenced through its name space: d:close() but not
> close().  You see when functions are included by namespace you set a name
> for they also go into a global local namespace.
> 
> Right now:
> include db.e -- includes into the global name space
> 
> include db.e as d -- includes into global namespace and namespace 'd'.
> 
> -- no way to put include db.e into a namespace 'd' exclusively.
> 
> 
> Perhaps you could use existing keywords in a new way:
> 
> include db.e as d, without global
> -- includes db.e into d but close() will call the builtin.  
> -- Even if there is a function called insert in db.e, calling insert() will
> fail,
> -- you must type d:insert().
> 
> Jeremy Cowgar wrote:
> > 
> > I create a db.e file that defines the word close. I then:
> > 
> > }}}
<eucode>
> > include db.e as d
> > 
> > --- do things
> > f = open(filename, "w")
> > 
> > -- later
> > close(f)
> > </eucode>
{{{

> > 
> > It called the database's close function, not the internal. So, even if you
> > use
> > a namespace, your included files cannot define functions by the same name as
> > an internal and you expect to continue to use an internal function?
> > 
> > --
> > Jeremy Cowgar
> > <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

new topic     » goto parent     » topic index » view message » categorize

9. Re: Namespace clobbering internals

I saw the idea of keeping symbols out of the global scope necessary for 
porting existing EUPHORIA applications and libraries to the new standard
library.
Imagine you have 12,000 lines of code and you wish to use this new standard 
library.  Can you imagine having to do a search and replace for every builtin 
to include an eu: namespace qualifier?

Perhaps it is just better to avoid the names of builtins in the first place
unless
you really want to override them.  Instead of open and close, the same kind of
thing could be called connect() and disconnect().

Shawn Pringle


Arthur Crump wrote:
> 
> 
>  "include db.e as d, without global"
> in a module looks more like a syntax to prevent a program which called 
> this module from receiving db.e, rather than this module not receiving 
> it without its namespace; an option I would like to see, incidentally.
> 
> Perhaps:
>  "include db.e as d only"
> might be sufficient.
> 
> However, Jeremy Cowgar's suggestion of a standard namespace such as eu 
> for builtin routines is equally good.
> 
> Arthur Crump, in Cheshire, England.
> 
> Shawn Pringle wrote:
> > 
> > This is what I tried to explain in the chat room.  We would like to put
> > included modules into a namespace exclusively so that a function such as
> > close could ONLY be referenced through its name space: d:close() but not
> > close().  You see when functions are included by namespace you set a name
> > for they also go into a global local namespace.
> > 
> > Right now:
> > include db.e -- includes into the global name space
> > 
> > include db.e as d -- includes into global namespace and namespace 'd'.
> > 
> > -- no way to put include db.e into a namespace 'd' exclusively.
> > 
> > 
> > Perhaps you could use existing keywords in a new way:
> > 
> > include db.e as d, without global
> > -- includes db.e into d but close() will call the builtin.  
> > -- Even if there is a function called insert in db.e, calling insert() will
> > fail,
> > -- you must type d:insert().
> > 
> > Jeremy Cowgar wrote:
> > > 
> > > I create a db.e file that defines the word close. I then:
> > > 
> > > }}}
<eucode>
> > > include db.e as d
> > > 
> > > --- do things
> > > f = open(filename, "w")
> > > 
> > > -- later
> > > close(f)
> > > </eucode>
{{{

> > > 
> > > It called the database's close function, not the internal. So, even if you
> > > use
> > > a namespace, your included files cannot define functions by the same name
> > > as
> > > an internal and you expect to continue to use an internal function?
> > > 
> > > --
> > > Jeremy Cowgar
> > > <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

new topic     » goto parent     » topic index » view message » categorize

10. Re: Namespace clobbering internals

Shawn Pringle wrote:
> 
> I saw the idea of keeping symbols out of the global scope necessary for 
> porting existing EUPHORIA applications and libraries to the new standard
> library.
> Imagine you have 12,000 lines of code and you wish to use this new standard
> 
> library.  Can you imagine having to do a search and replace for every builtin
> 
> to include an eu: namespace qualifier?
> 
> Perhaps it is just better to avoid the names of builtins in the first place
> unless 
> you really want to override them.  Instead of open and close, the same kind
> of
> thing could be called connect() and disconnect().
> 
> Shawn Pringle

But you wouldn't have to do that really (although automation certainly eases the
task). You would only have to add a namespace qualifier to symbols that clashed.

And if a namespace keyword was adopted as has been suggested then I think that
conflicts would be far easier to fix.

--
A complex system that works is invariably found to have evolved from a simple
system that works.
--John Gall's 15th law of Systemantics.

"Premature optimization is the root of all evil in programming."
--C.A.R. Hoare

j.

new topic     » goto parent     » topic index » view message » categorize

11. Re: Namespace clobbering internals

Jason Gade wrote:
> 
> Shawn Pringle wrote:
> > 
> > I saw the idea of keeping symbols out of the global scope necessary for 
> > porting existing EUPHORIA applications and libraries to the new standard
> > library.
> > Imagine you have 12,000 lines of code and you wish to use this new standard
> > 
> > library.  Can you imagine having to do a search and replace for every
> > builtin
> > 
> > to include an eu: namespace qualifier?
> > 
> 
> But you wouldn't have to do that really (although automation certainly eases
> the task). You would only have to add a namespace qualifier to symbols that
> clashed.
> 

I think Shawn is right. Say, you have your program that uses the function
close() many times to close a file. Then you include, say, my pgsql.e file which
also defines close().

Now, everywhere in his code that contains close() (as referring to the built-in
close()), would require a prefix of eu: added. Otherwise, it would call the
close() defined in pgsql.e, even though pgsql.e included inside of a namespace.

I think I am back to my original thoughts on this:

http://www.openeuphoria.org/EUforum/m20234.html

Now, Matt replied that it would break existing code, as people who have
over-ridden built-in's intentionally to have their own version of printf() for
use while debugging or something.

Depending on how many people do that, it may just be better to realize that as
soon as anyone anywhere defines a function by the name of an internal, then
you've lost the ability to use that internal (as soon as you include that file in
your code that is). That doesn't seem quite right, but that is how things are
looking right now?

--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » goto parent     » topic index » view message » categorize

12. Re: Namespace clobbering internals

Jeremy Cowgar wrote:
> 
> Jason Gade wrote:
> > 
> > Shawn Pringle wrote:
> > > 
> > > I saw the idea of keeping symbols out of the global scope necessary for 
> > > porting existing EUPHORIA applications and libraries to the new standard
> > > library.
> > > Imagine you have 12,000 lines of code and you wish to use this new
> > > standard
> > > 
> > > library.  Can you imagine having to do a search and replace for every
> > > builtin
> > > 
> > > to include an eu: namespace qualifier?
> > > 
> > 
> > But you wouldn't have to do that really (although automation certainly eases
> > the task). You would only have to add a namespace qualifier to symbols that
> > clashed.
> > 
> 
> I think Shawn is right. Say, you have your program that uses the function
> close()
> many times to close a file. Then you include, say, my pgsql.e file which also
> defines close(). 
> 
> Now, everywhere in his code that contains close() (as referring to the
> built-in
> close()), would require a prefix of eu: added. Otherwise, it would call the
> close() defined in pgsql.e, even though pgsql.e included inside of a
> namespace.
> 
> I think I am back to my original thoughts on this:
> 
> <a
> href="http://www.openeuphoria.org/EUforum/m20234.html">http://www.openeuphoria.org/EUforum/m20234.html</a>
> 
> Now, Matt replied that it would break existing code, as people who have
> over-ridden
> built-in's intentionally to have their own version of printf() for use while
> debugging or something.
> 
> Depending on how many people do that, it may just be better to realize that
> as soon as anyone anywhere defines a function by the name of an internal, then
> you've lost the ability to use that internal (as soon as you include that file
> in your code that is). That doesn't seem quite right, but that is how things
> are looking right now? 
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

Consider this:
(eu.e:)
global procedure old_close( integer fd )
    close( fd )
end procedure

global procedure close( integer fd )
    close( fd )
end procedure

global function open( sequence filename, sequence access )
    open( filename, access )
end function

----

main.ex
include eu.e as eu
include db.e as db
integer fd
object line
fd = eu:open( "c:\autoexec.bat", "r" )
line = gets(fd)
while sequence(line)
  ? line
  line = gets(fd)
end while
old_close( fd )


You see you can setup a builtin namespace without touching the backend source.
You can still access the builtin but you have to alter how you access it.  This
would break any large project: win32lib.ew, ide.exw and thus inhibit the 
standard library's acceptance to large existing projects.  This is what we did
for redefining printf().  Often the new printf would need to call the old printf
you needed to give the old printf another name: old_printf.

Shawn

new topic     » goto parent     » topic index » view message » categorize

13. Re: Namespace clobbering internals

Jeremy Cowgar wrote:
> 
> Jason Gade wrote:
> > 
> > Shawn Pringle wrote:
> > > 
> > > I saw the idea of keeping symbols out of the global scope necessary for 
> > > porting existing EUPHORIA applications and libraries to the new 
> > > standard library. Imagine you have 12,000 lines of code and you wish
> > > to use this new standard library.  Can you imagine having to do a
> > > search and replace for every builtin to include an eu: namespace
> > > qualifier?
> > 
> > But you wouldn't have to do that really (although automation certainly
> > eases the task). You would only have to add a namespace qualifier to
> > symbols that clashed.
> > 
> 
> I think Shawn is right. Say, you have your program that uses the function
> close() many times to close a file. Then you include, say, my pgsql.e file
> which also defines close(). 
> 
> Now, everywhere in his code that contains close() (as referring to the
> built-in close()), would require a prefix of eu: added. Otherwise, it
> would call the close() defined in pgsql.e, even though pgsql.e included
> inside of a namespace.

Well, remember, this is only if he wants to do add something new to his
existing 12KLOC.  If he keeps using the libraries he has, nothing changes.
How many built-ins are we talking about overriding?
 
> I think I am back to my original thoughts on this:
> 
> http://www.openeuphoria.org/EUforum/m20234.html
> 
> Now, Matt replied that it would break existing code, as people who have
> over-ridden built-in's intentionally to have their own version of printf()
> for use while debugging or something.

Yes.  But also consider your hypothetical pgsql.e.  It couldn't use its
own close() function, unless it defines a namespace for itself.  This
fails the principle of least surprise.

> Depending on how many people do that, it may just be better to realize
> that as soon as anyone anywhere defines a function by the name of an
> internal, then you've lost the ability to use that internal (as soon as
> you include that file in your code that is). That doesn't seem quite right,
> but that is how things are looking right now? 

I remain unconvinced that refactoring your code to accommodate a new 
library is too much of a burden.

Matt

new topic     » goto parent     » topic index » view message » categorize

14. Re: Namespace clobbering internals

Matt Lewis wrote:
> 
> How many built-ins are we talking about overriding?
>

Here are some common ones that would make libraries easier if we can override
them. The reason I say this, is why come up with 20 creative names for the same
task just to prevent collisions. Now, if I want to delete a record from a
database I have to use delete, then to remove something from a map, I have to use
vanish, then to delete an item in a sequence I have to remove, etc... If diff
libs could all use remove or delete to remove or delete something, then it makes
things easier.

append, prepend, remove, length, compare, equal, find, match, sort, open, close.

That's just real quick off the top of my head. Again, being able to use these
function names makes programming libraries and using libraries simpler.

map:length() for instance. Instead of coming up with map:size(),
map:length_of(), map:mass(), map:volume(), map:extent(), map:porpotion(), etc...

or...

map:remove() instead of map:delete(), map:take(), map:take_off(),
map:withdraw(), etc...

Again, this creates a simpler API. One problem with programming in Forth is the
requirement of every single word has to be a new name, so when programming
anything sizeable in forth you wind up becoming an English scholar and your
dictionary becomes your greatest tool in programming. You then come up with names
that are so very similar that later you even question what it does.

> 
> Yes.  But also consider your hypothetical pgsql.e.  It couldn't use its
> own close() function, unless it defines a namespace for itself.  This
> fails the principle of least surprise.
>

Yes, that's a problem. I wonder if in addition to a eu: namespace if we should
borrow a good idea from the OO people (not to make Euphoria OO, and not to
suggest that I like Java better than Euphoria, but why not learn from other
languages? To not learn from other languages is not very smart), self:, this:,
current:, me: or something like that.

Just more thinking about the subject.

Matt, I think the eu: namespace is a critical addition, even if we do or do not
use it to solve some of these problems we are speaking of right now. What it will
do is give, in example, the pgsql.e file the ability to call the built-in close()
or it's own close(). I do not think anyone will complain if we add the eu:
namespace as it will not break a thing and will only help in situations. Can you
give me a pointer or direction in implementing this?

--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » goto parent     » topic index » view message » categorize

15. Re: Namespace clobbering internals

Jeremy Cowgar wrote:
> 
> Jason Gade wrote:
> > 
> > Shawn Pringle wrote:
> > > 
> > > I saw the idea of keeping symbols out of the global scope necessary for 
> > > porting existing EUPHORIA applications and libraries to the new standard
> > > library.
> > > Imagine you have 12,000 lines of code and you wish to use this new
> > > standard
> > > 
> > > library.  Can you imagine having to do a search and replace for every
> > > builtin
> > > 
> > > to include an eu: namespace qualifier?
> > > 
> > 
> > But you wouldn't have to do that really (although automation certainly eases
> > the task). You would only have to add a namespace qualifier to symbols that
> > clashed.
> > 
> 
> I think Shawn is right. Say, you have your program that uses the function
> close()
> many times to close a file. Then you include, say, my pgsql.e file which also
> defines close(). 
> 
> Now, everywhere in his code that contains close() (as referring to the
> built-in
> close()), would require a prefix of eu: added. Otherwise, it would call the
> close() defined in pgsql.e, even though pgsql.e included inside of a
> namespace.
> 
> I think I am back to my original thoughts on this:
> 
> <a
> href="http://www.openeuphoria.org/EUforum/m20234.html">http://www.openeuphoria.org/EUforum/m20234.html</a>
> 
> Now, Matt replied that it would break existing code, as people who have
> over-ridden
> built-in's intentionally to have their own version of printf() for use while
> debugging or something.
> 
> Depending on how many people do that, it may just be better to realize that
> as soon as anyone anywhere defines a function by the name of an internal, then
> you've lost the ability to use that internal (as soon as you include that file
> in your code that is). That doesn't seem quite right, but that is how things
> are looking right now? 
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

If someone somewhere overrides a builtin, I guess that the purpose is to extend
the builtin without changing its normal processing. This way, the user can take
advantage of the enhancements without bothering to use yet another name[space].
Then, what is the point of insisting on calling the builtin?

For the sake of peace of mind, something easy can be done. Usually, extending a
builtin takes the following form:
procedure print_wrapped(whatever)
-- wrap builtin as a regular routine, because builtins have no routine_id
print(whatever)
end procedure

-- now we have an alternate way of calling print()
constant print_id=routine_id("print_wrapped")

-- now redefine the builtin, while elying on it if the extensions are not 
-- needed on some call.
global procedure print(whatever)
-- Very, very unfortunately, the signature cannot be changed.

if my_own_procesing() then
    my_smecial_code()
else
    call_proc(print_id,{whatever})
end if
end procedure


Extending a builtin otherwise would have to be discouraged. Notice that, if
print_id is made global, then you can call the vintage print() again.

Some piece of (good) kludgy ol' Eu. In most languages, the proecess is very
straightforward.
CChris

new topic     » goto parent     » topic index » view message » categorize

16. Re: Namespace clobbering internals

CChris wrote:
> 
> If someone somewhere overrides a builtin, I guess that the purpose is to
> extend
> the builtin without changing its normal processing. 

This is not the case, Please see my post:

http://www.openeuphoria.org/EUforum/m20279.html

--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » goto parent     » topic index » view message » categorize

17. Re: Namespace clobbering internals

Jeremy Cowgar wrote:
> 
> CChris wrote:
> > 
> > If someone somewhere overrides a builtin, I guess that the purpose is to
> > extend
> > the builtin without changing its normal processing. 
> 
> This is not the case, Please see my post:
> 
> <a
> href="http://www.openeuphoria.org/EUforum/m20279.html">http://www.openeuphoria.org/EUforum/m20279.html</a>
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

What you describe isn't overriding, it's overloading. 

The namespace proposals so far (default namespace in include, eu namespace for
builtins) should enable overloading.

Unless I'm missing something in the conversation.

--
A complex system that works is invariably found to have evolved from a simple
system that works.
--John Gall's 15th law of Systemantics.

"Premature optimization is the root of all evil in programming."
--C.A.R. Hoare

j.

new topic     » goto parent     » topic index » view message » categorize

18. Re: Namespace clobbering internals

Jason Gade wrote:
> 
> 
> What you describe isn't overriding, it's overloading. 
> 

Yes, but the original problem is that there is no way to overload, it is
overriding.

> The namespace proposals so far (default namespace in include, eu namespace for
> builtins) should enable overloading.

Except that it will force people to use eu: in their code even when they include
map.e as map ... Let's say map overload's the find() function (may be a dumb
example, but an example).

include map.e as map

map:map m
m = map:new()
m = map:put(m, "name", "Jason")
m = map:find(m, "Jason")

sequence e
e = {1,2,3}
? find(3, e)


So, the lower part dealing with the sequence was code that existed already in
programmer Joe's code. Now Joe makes use of the new map. Well, his find() for the
sequence e is now broke. He has to go back and prefix find() with eu:

Now, as Matt said, it may not be that big of a conversion path for people to do
that. My original thinking was in the above example, find() exists in both the
built-in namespace and the map namespace. If there is a conflict and no namespace
is given, then Euphoria should chose the built-in function, however, that would
take away the ability to override a built-in (again as Matt pointed out to me).

--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » goto parent     » topic index » view message » categorize

19. Re: Namespace clobbering internals

Jeremy Cowgar wrote:
> 
> CChris wrote:
> > 
> > If someone somewhere overrides a builtin, I guess that the purpose is to
> > extend
> > the builtin without changing its normal processing. 
> 
> This is not the case, Please see my post:
> 
> <a
> href="http://www.openeuphoria.org/EUforum/m20279.html">http://www.openeuphoria.org/EUforum/m20279.html</a>
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

I see.

The overloading of a single routine name to perform similar actions on different
sorts of objects has been consistently fought off on this list. Of course, as a
user of some OO languages (mostly Eiffel and less Delphi), I think that
overloading would make the language much easier to learn and use. I'd be
delighted if we could at last come back from this nonsense of "if it does
something else, give it another name".

Nevertheless, extensions in the way I described are also useful, and should be
made posible *as well*.

CChris

new topic     » goto parent     » topic index » view message » categorize

20. Re: Namespace clobbering internals

Jason Gade wrote:
> 
> Jeremy Cowgar wrote:
> > 
> > CChris wrote:
> > > 
> > > If someone somewhere overrides a builtin, I guess that the purpose is to
> > > extend
> > > the builtin without changing its normal processing. 
> > 
> > This is not the case, Please see my post:
> > 
> > <a
> > href="http://www.openeuphoria.org/EUforum/m20279.html">http://www.openeuphoria.org/EUforum/m20279.html</a>
> > 
> > --
> > Jeremy Cowgar
> > <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>
> 
> What you describe isn't overriding, it's overloading. 
> 
> The namespace proposals so far (default namespace in include, eu namespace for
> builtins) should enable overloading.
> 
> Unless I'm missing something in the conversation.
> 
> --
> A complex system that works is invariably found to have evolved from a simple
> system that works.
> --John Gall's 15th law of Systemantics.
> 
> "Premature optimization is the root of all evil in programming."
> --C.A.R. Hoare
> 
> j.

Yes, they would. 
CChris

new topic     » goto parent     » topic index » view message » categorize

21. Re: Namespace clobbering internals

Jeremy Cowgar wrote:
> 
> Jason Gade wrote:
> > 
> > 
> > What you describe isn't overriding, it's overloading. 
> > 
> 
> Yes, but the original problem is that there is no way to overload, it is
> overriding.
> 
> > The namespace proposals so far (default namespace in include, eu namespace
> > for
> > builtins) should enable overloading.
> 
> Except that it will force people to use eu: in their code even when they
> include
> map.e as map ... Let's say map overload's the find() function (may be a dumb
> example, but an example).
> 
> }}}
<eucode>
> include map.e as map
> 
> map:map m
> m = map:new()
> m = map:put(m, "name", "Jason")
> m = map:find(m, "Jason")
> 
> sequence e
> e = {1,2,3}
> ? find(3, e)
> </eucode>
{{{

> 
> So, the lower part dealing with the sequence was code that existed already in
> programmer Joe's code. Now Joe makes use of the new map. Well, his find() for
> the sequence e is now broke. He has to go back and prefix find() with eu:
> 
> Now, as Matt said, it may not be that big of a conversion path for people to
> do that. My original thinking was in the above example, find() exists in both
> the built-in namespace and the map namespace. If there is a conflict and no
> namespace is given, then Euphoria should chose the built-in function, however,
> that would take away the ability to override a built-in (again as Matt pointed
> out to me).
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

I understand the problem a bit better now. A proper solution requires some
thought I think...

--
A complex system that works is invariably found to have evolved from a simple
system that works.
--John Gall's 15th law of Systemantics.

"Premature optimization is the root of all evil in programming."
--C.A.R. Hoare

j.

new topic     » goto parent     » topic index » view message » categorize

22. Re: Namespace clobbering internals

If you set builtins as always being the one used when a namespace is not 
specified you will break overloading.  If you leave the interpreter the 
way it is, your new library's use of functions with the same names as 
builtins will break much more code than what's in print.e.  A 
third alternative is to introduce some kind of hiding into a namespace.
A fourth alternative involves avoiding any builtin names.

When I say, hiding objects into a namespace.  I would like you to 
suppose that insert() is a routine defined in db.e.  
'include db.e' means you can only access db.e's insert() function as insert().
'include db.e as db' means you can access db.e's insert() function as 
both insert() and db:insert().  You could hack  the backend such that
that allows you can get access to insert() as db:insert() but not as 
insert().  I don't like the idea of modifying the backend, though.

The fourth alternative is, you can use the same method names over and over if
you
ensure they are not builtins.  All new libraries can use routines names
over and over so long as the name doesn't appear twice in the same file.  So,
you may need to find synonyms for some builtin names but you only need to find
one synonym for each one.  There is no modifying the backend and you wont break
any existing code.

The fourth alternative, I have to say is less bug proned than the third
alternative
since you are not modifying the interpreter C-source itself.  You don't need
to put the builtins into their own namespace because you purposely avoid using
builtins.  This means that large programs like Judith's IDE could use it without
renaming or namespaceing other things.

The third alternative has appeal to me.  I think it would be neat to do a kind
of overloading only for things inside a namespace.  You might introduce bugs
into
the EU interpreter but large programs could then use this library without
renaming
or namespacing other things.

The first two ideas are well understood by anyone who reads Matt's posts so I
will
not talk more about them here. :)

Shawn

new topic     » goto parent     » topic index » view message » categorize

23. Re: Namespace clobbering internals

I must admit I have not followed your discussion from the start, but one simpler
solution seems to me rather obvious: instead of adding ever more convoluted
namespace rules, introduce a special, restricted type of global identifiers,
which will have to be *always* preceded by a context specifier. A single new
keyword will be required, say 'export' instead of 'global'.

Using example similar to Jason's:

--  map.e

export type map(...
export function new(...
export function put(...
export function find(...


--  myprog.ex

include map.e as map

integer index
map:map m
m = map:new()
m = map:put(m, "name", "Jason")
index = map:find(m, "Jason")

sequence e
e = {1,2,3}
? find(3, e)    -- system function not clobbered!

The globals can stay as they are, but they should be used for important,
system-wide identifiers only. Their wholesale use should be strongly discouraged.

This approach will leave the global space uncluttered, programs more
understandable, and not much, if any legacy code will be broken.

jiri

new topic     » goto parent     » topic index » view message » categorize

24. Re: Namespace clobbering internals

jiri babor wrote:
> 
> 
> keyword will be required, say 'export' instead of 'global'.
> 

I wonder if the inverse might be helpful? override ... for instance, say you
want to override the print function:

override function close(...)
 --- code
end function


Now, those that wish to override internals can, and those that just want to make
their own close() function for a database, or a PDF writer, or who knows what,
they can.

--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » goto parent     » topic index » view message » categorize

25. Re: Namespace clobbering internals

jiri babor wrote:
> 
> I must admit I have not followed your discussion from the start, but one
> simpler solution seems to me rather obvious: instead of adding ever more
> convoluted namespace rules, introduce a special, restricted type of global
> identifiers, which will have to be *always* preceded by a context specifier.
> A single new keyword will be required, say 'export' instead of 'global'.

Of *course* it's obvious to you, Jiri.  Seriously, though, it's good to 
hear from you again.

<snip>

> The globals can stay as they are, but they should be used for important,
> system-wide identifiers only. Their wholesale use should be strongly
> discouraged. 
> 
> This approach will leave the global space uncluttered, programs more
> understandable, and not much, if any legacy code will be broken.

Yes, this gets into the 'packaging' topic that has been discussed a bit.  I
think this is very similar to what I've proposed in that arena.  I'd add a
little to this idea, to say that you have to use the namespace that is
specific to that file, because a namespace also can apply to the globals
included by the file given the namespace.
-- app.ex
include foo.e as foo
include bar.e as bar
foo:baz()         -- ok
bar:bar()         -- ok
foo:bar()         -- error!

-- foo.e
include bar.e as bar
...
bar:bar()

-- bar.e
export procedure bar()
end procedure
global procedure baz()
end procedure


I like this because no matter where bar.e goes, the behavior stays the same,
and it's scope is obvious.  I'm contrasting this to CChris' packaging 
proposal, where we would have to  add some additional packaging information 
in other files.

This would allow library writers to spread out among multiple files (making
their lives easier) but without exposing the internals to library users,
who can possibly come to rely on something meant to be internal, and subject
to change without notice.

Matt

new topic     » goto parent     » topic index » view message » categorize

26. Re: Namespace clobbering internals

I don't know if anyone else is, but I'm having troubles following all the
suggestions, the pros/cons, etc... I wonder if we should create a wiki page for a
Namespace plan or something? Seems kind of hard to act on any of this because it
seems we've made no decision and it's hard to even decide what choices there are
to make a decision about, or for that matter, what the problem actually is any
more smile

--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » goto parent     » topic index » view message » categorize

27. Re: Namespace clobbering internals

Jeremy Cowgar wrote:
> 
> I don't know if anyone else is, but I'm having troubles following all the
> suggestions,
> the pros/cons, etc... I wonder if we should create a wiki page for a Namespace
> plan or
> something? Seems kind of hard to act on any of this because it seems we've
> made no decision
> and it's hard to even decide what choices there are to make a decision about,
> or for
> that matter, what the problem actually is any more smile

In fact, there already is one, although it's out of date now, as it describes
stuff already implemented:

http://rapideuphoria.wiki.sourceforge.net/Namespace_Resolution

Matt

new topic     » goto parent     » topic index » view message » categorize

28. Re: Namespace clobbering internals

Jeremy Cowgar wrote:
> 
> jiri babor wrote:
> > 
> > 
> > keyword will be required, say 'export' instead of 'global'.
> > 
> 
> I wonder if the inverse might be helpful? override ... for instance, say you
> want to override the print function:
> 
> }}}
<eucode>
> override function close(...)
>  --- code
> end function
> </eucode>
{{{

> 
> Now, those that wish to override internals can, and those that just want to
> make their own close() function for a database, or a PDF writer, or who knows
> what, they can.
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

You know, I was reading some Python docs last night, for no particular reason,
and one of their standards and practices for naming routines that might clash
with a built-in is to append an underscore to the identifier:

function open_(sequence name)
    -- Do stuff here
end function


Not a permanent solution because we really do need to decide how scopes and
namespaces should work better, but maybe a good temporary solution since we never
seem to be able to come to a consensus.

--
A complex system that works is invariably found to have evolved from a simple
system that works.
--John Gall's 15th law of Systemantics.

"Premature optimization is the root of all evil in programming."
--C.A.R. Hoare

j.

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu