Re: use-package & name conflict: why they are not deferred?
- From: Kaz Kylheku <kkylheku@xxxxxxxxx>
- Date: Mon, 27 Oct 2008 21:36:31 +0000 (UTC)
On 2008-10-26, budden <budden01@xxxxxxxxxx> wrote:
In "modern" OO languages such as C++ or Java, each class in fact
introduces its own namespace.
But these are not symbol namespaces but rather referential namespaces.
All symbols in C++ are in fact in one global namespace.
Given foo::x and bar::x, you are actually talking about three names: foo, bar
and x. The two x's are actually the same name.
So for instance if B is base class, D is derived, then D::x hides B::x.
There are more quirks in the design. Suppose that B::x is a virtual function
and D::x is also a function, and has the same type signature. D::x then
overrides B::x.
If a D object is accessed through a reference R to B, then R.x actually refers
to D::x. However, R.B::x refers to B::x.
When you use a slot/method of a class in
a definition of other method, you are into that namespace, so you
don't need to fully qualify slots/members of that class.
Really? See above. If you're in the scope of class B, and call a function x,
you might actually be going to D::x, even though nothing is known about any D
in that scope. You have to use scope resolution to reach B::x.
Virtual functions can sneak up on you. Suppose a base class designer decides to
flip some regular function into being virtual. Oops; all functions in derived
classes which have the same name and a compatible signature are now overrides
of that function.
C++ has a pitifully stupid design with regard to how things are named, scoped
and referenced.
It is
reasonable as class might encapsulate many or most of the data
required for method definition. This leads to shorter, more easily
reading code. In Perl, class is distinctly bound to namespace. Pascal
has a with construct which joins namespaces from several records.
It's not surprising you're a fan of Pascal's WITH.
Basically, you like brainadamaged things and you want Lisp to be that way.
Let's look at WITH:
(* in a procedure *)
VAR x : INTEGER;
WITH some_record ; BEGIN
y := func(x);
END
Above, func(x) refers to the local variable x, and y refers to some_record.y.
But suppose someone now maintains the program, and adds a field called x to
some_record. Oops! The stupid WITH statement now makes x refer to the x in the
record! The meaning of the assignment statement silently changes, and the
software breaks.
Think about how idiotic that is: a change done in some remote location of the
program, perhaps in another file, changes a meaning of a local variable
reference. Oops, I mean, what other file; Pascal originally didn't have
modules.
Modula-3 has a sanely designed WITH construct, which is similar to Lisp's
SYMBOL-MACROLET. It's something like:
WITH y = some_record.y, x = some_record.x[i] ; DO
...
END
See, you explicitly write every symbol that is introduced into the scope. There
are no hidden clashes.
Ada doesn't inherit Pascal's WITH statement either. Ada has a WITH statement
which does something else: it's used for bringing in packages.
Oberon has a WITH keyword, but the semantics is completely different something
like Lisp's TYPECASE.
So if we look at some of the predominant descendants of Pascal, we find that
the designers have not only repented the WITH mistake, but they sealed its fate
by reusing the word for other uses!
See, by redefining WITH, the language definitions of Ada, Modula 3 and Oberon
prevent implementors from providing a Pascal WITH as a backward-compatibility
extension for doing quick-and-dirty ports of questionable Pascal source.
Ada's WITH has the properties you like: you can use WITH to import packages
with clashing symbols. The clashes are identified as ambiguous at the point
where the symbols are used. This is perfectly fine in a language with a
well-defined compile time, in which all of the symbolic drama is played out to
its completion. If an Ada program builds with no ambiguous symbol references,
then there is no further worry.
Human reader is clever enough to catch a "context".
That's great if you are writing programs to be executed by humans,
rather than machines.
But if I try to combine this approach to CL standard "conflict free"
package system state, this becomes practically unusable due to symbol
clashes. I think lisp loses there in a competition to modern
languages.
The question is, do we want to win in a race for the bottom?
.
- Follow-Ups:
- Re: use-package & name conflict: why they are not deferred?
- From: John Thingstad
- Re: use-package & name conflict: why they are not deferred?
- References:
- use-package & name conflict: why they are not deferred?
- From: budden
- Re: use-package & name conflict: why they are not deferred?
- From: Kaz Kylheku
- Re: use-package & name conflict: why they are not deferred?
- From: budden
- Re: use-package & name conflict: why they are not deferred?
- From: budden
- use-package & name conflict: why they are not deferred?
- Prev by Date: Re: naming conventions for slot accessors
- Next by Date: Re: OT: Ruby evangelists in c.l.l
- Previous by thread: Re: use-package & name conflict: why they are not deferred?
- Next by thread: Re: use-package & name conflict: why they are not deferred?
- Index(es):
Relevant Pages
|