View mode: basic / threaded / horizontal-split · Log in · Help
March 28, 2003
Re: null == o?
Heh, sooner or later we have to agree on something.  Don't we? :-)

Anyway, here's what I think:

> > Okay, I love C++ but something is entirely wrong if such an antiquated
> > language manages to provide the most reliable solution to something as
> basic
> > as this (at least if you're not a newbie).
>
> Why do you say it's basic? C#, D & Java all attempt to fudge the
dichotomous
> nature of instances and their pointers for the sake of a (what some would
> say specious) syntactic nicety. For the record, I'm not one of them in
> principle, but no language other than C++ has yet managed this distinction
> in a sensible and complete fashion. D is coming the closest, but if we
have
> to manually test for identity before we can test for equality then all
that
> syntactic nicety is just a waste of time.
>
> Whatever anyone's opinion, I fail to see how this is a simple issue.

Basic because it's a problem that even simple programs could get bitten by.
Basic, but definitely not simple.

> > I think anything we come up with is just going to be a kludge around a
> > fundamental problem that is created by not automatically initializing
> > objects when they are declared.
>
> Whether you like it or not, a big reason that C, C++ and D have been
> designed the way they have is for efficiency. C & C++ owe a lot of their
> sucecss to this. You're not going to sell D as anything other than a lame
> puppy if it cannot demonstrate similar, or better, levels of efficiency
than
> its forebears/peers. The work Walter and I have been doing in the last
week
> or so on performance comparisons has shown that D does indeed kick the
arse
> of most of its peers in a number of areas; being a C++ diehard myself,
this
> is a significant factor in my personnally starting to think more and more
of
> using D seriously.

C++ also happens to be the only member of the bunch that does initialize
instances automatically.  It's no accident that the equality identity
problem is a non-issue in C++.

> > I wonder if it wouldn't be better to have the language implicitly create
> an
> > instance of the object when it is declared if it's not done explicitly:
> > blah blab;
> > blah blab=new blah;    //these to lines are equivalent
> > //if blab is global, the instance would be created before main is called
>
> [Q: I presume that D currently initialises an uninitialised variable to
> null. Is this correct? If it doesn't, it should.]

Yeah, it does.

> I can't agree with this. Putting aside the fact that it could result in
some
> horrible inefficiencies for non-trivial class instances, it is overly
> restrictive. Simplistically
>
> class Something
> {}
>
> class QuiteSomething
>   : Something
> {}
>
> class AmazingSomething
>   : Something
> {}
>
>
> // Factory object
> Something CreateSomethingSpecial(char[] parameterisation)
> {
>   Something    something = null; // The default case
>
>   if(parameterisation == "quite-special")
>   {
>     something = new QuiteSomething();
>   }
>   else if(parameterisation == "amazing")
>   {
>     something = new AmazingSomething();
>   }
>   else if
>   {
>     . . . // etc. etc.
>
>   return something;
> }
>
> What you're telling me is that I cannot write it like this. Either I have
to
> have multiple return statements - which is not my style - or I have cannot
> return null so must use exceptions - which may not be
appropriate/desirable.
> What have we gained with this restriction?
>

I was going to say that you could use pointers to do this, but I think I
found a compiler bug (or a very weird restriction, or i'm doing something
very wrong) so I'll post that on a new thread.

> > You could then say that it is illegal to assign null to an object
> reference.
> > I don't think it makes much sense to have a null object reference most
of
> > the time anyhow.
>
> I have to strongly disagree with this, sorry. :)
>
> null is a _very_ useful state. Without it we'd either have to have signal
> objects, which is inefficient, or use exceptions for nearly everything.
> >  And it is easy to add a "bit empty;" line to a class for
> > the few times when something like that might be useful.

:-)  Yeah, a bit empty field may not be the most brilliant solution.

> > This would avoid the problem completely.  This could in theory cause a
> > performance hit, but I think that in practice that would happen seldom
> > enough that it would be more than worth the robustness.  How often do
you
> > declare something and don't instantiate it almost immediately?  Even
when
> > you do, it's likely to be a one time only thing--that is to say, it's
> > probably not going to be something that happens over and over again
inside
> a
> > loop or recursive function.
> >
> >
>
>
> All of the trouble so far is based on a desire to handle the mess of
> equivalence/identity in languages that use references as pointers (i.e.
the
> references can be null). Unless there is an efficient built-in, but
> potentially user-tailorable, handling of this then we might as well get
rid
> of the == and === operators entirely, and do everything with
> Object.Equals(o1, o2) and Object.EqualsReference(o1, o2) methods, with all
> the glamour that would entail.
>

Point taken.  I'm not proposing we scratch reference altogether, or even
that we get rid of explicit "new"s.  I just think it should be illegal to
have a reference to nothing.
March 28, 2003
Re: null == o?
"Benji Smith" <Benji_member@pathlink.com> wrote in message
news:b5ven6$233d$1@digitaldaemon.com...
> I wholeheartedly agree. I need to be able to trust that I can use == and
===
> without worrying about access violations for null pointers.

I'm going to disagree with a couple points. First of all, I'm going to
disagree with the notion that an access violation is something bad. I worked
for 10 years on MSDOS programs were accessing null pointers scrambled the
operating system. I *like* having a program bug promptly generate an
exception and stop. Those bugs tend to be easy to find. The hard ones are
where your program silently continues on chugging, corrupting data, and
obfuscating its origins. It's a good thing when cases not accounted for
cause exceptions.

The == operator is defined as checking the equivalence of the *contents* of
the object references. If the reference is null, it's a program bug and
should properly generate an exception. It's analogous to:

   Foo p = null;
   p.bar();

which will also generate an exception.

A null reference can be a legitimate value in a program, or it could be
caused by forgetting to initialize a reference. By coding in an explicit
check for null, you're documenting that it can be null. By leaving out such
a check, you're implicitly documenting that it cannot be null.
March 28, 2003
Re: null == o?
"Matthew Wilson" <dmd@synesis.com.au> wrote in message
news:b60e8s$2tg8$1@digitaldaemon.com...
> [Q: I presume that D currently initialises an uninitialised variable to
> null. Is this correct? If it doesn't, it should.]

That's correct.
March 28, 2003
Re: null == o?
I agree that access violations have their place, and make use of them on
occasion, but disagree that this is one.

D, like C# and Java, "pretends" that a pointer to an instance is a "thing"
that can be treated like the instance itself. This is evident in the fact
that we wish to, and are able to, apply == to references.

This pretence is a dishonesty, one which is obvious when one considers how
C++ does it. However, when a language does not deal with pointers, the
dishonesty can be benign and useful.

I don't have a problem with this pretence, so long as it's consistent. If
you want objects to be treated "like the ints", then you have to do it
fully. This argument is well worn wrt C++ operator overloading issues, but
applies all round.

When I write code that compares two entities that are int, I don't have to
write

int    i1 = . . .
int    i2 = . . .

if( i1 !== null &&
   i2 !== null &&
   i1 == i2)
{

That would be ludicrous. So why should I have to do it with objects? Object
references should either consistently behave as built-ins in expressions, or
they should be completely different and require different syntax. This is
like having one's syntactic convenience without responsibility for caring
for the syntax. If we can't have that responsibility, then we should eschew
the syntactic convenience and just accept that we have to use Object method
calls for equivalence comparison and, in that case, for identity also.
Either make == and === work in a thoroughly consistent way, or not have them
at all.

Furthermore, since D has templates - you'll have to bear with me on this
one, as I'm a real neophyte with D's template syntax - is it not likely that
we'd have a template that would work with built-in types and with object
references. How would this work? Would we have to specialise on the
built-ins? (What's the point of the template, in that case?) Would we have
checks against null for the built-ins? (I can't imagine this'd compile,
would it?) Would we be forced to write it assuming that the references would
be non-null, since we would not be able to check for that? It all sounds
grim.

The Java situation is totally stupid, but at least it's obvious, and one
quickly gets used to it (though I still forget when I'm flitting between
languages). C#'s optional operator overloading is seemingly less stupid, and
_far_ more convenient, but it's all the more dangerous because it's
partially hidden. What you're saying for D seems an even deeper and more
insidious version, whereby it is more sensible and seemingly useful than
both Java and C#, but not quite sensible enough, and therefore more
dangerous than either of them.

Major wart. Sorry.

"Walter" <walter@digitalmars.com> wrote in message
news:b60uqc$7pi$1@digitaldaemon.com...
>
> "Benji Smith" <Benji_member@pathlink.com> wrote in message
> news:b5ven6$233d$1@digitaldaemon.com...
> > I wholeheartedly agree. I need to be able to trust that I can use == and
> ===
> > without worrying about access violations for null pointers.
>
> I'm going to disagree with a couple points. First of all, I'm going to
> disagree with the notion that an access violation is something bad. I
worked
> for 10 years on MSDOS programs were accessing null pointers scrambled the
> operating system. I *like* having a program bug promptly generate an
> exception and stop. Those bugs tend to be easy to find. The hard ones are
> where your program silently continues on chugging, corrupting data, and
> obfuscating its origins. It's a good thing when cases not accounted for
> cause exceptions.
>
> The == operator is defined as checking the equivalence of the *contents*
of
> the object references. If the reference is null, it's a program bug and
> should properly generate an exception. It's analogous to:
>
>     Foo p = null;
>     p.bar();
>
> which will also generate an exception.
>
> A null reference can be a legitimate value in a program, or it could be
> caused by forgetting to initialize a reference. By coding in an explicit
> check for null, you're documenting that it can be null. By leaving out
such
> a check, you're implicitly documenting that it cannot be null.
>
>
March 28, 2003
Re: null == o?
Ok, I'll kick in with a very very old point of view on the topic that 
dates back to the beginning of time...

Operator overloading should not be implemented as methods.  They should 
be implemented as overloaded functions at the module level.  Then, this 
whole problem goes away.  Besides, mathematically, a binary operator's 
operands have equal status.  Why pass one to a method of the other? 
It's just a stupid trick to try to avoid writing module-level routines.

The fact that we can't even define the == operator without worrying 
about the LEFT operand being null (but not the right) clearly shows the 
flaw in C++ style operator overloading.

Bill
March 28, 2003
Re: null == o?
In article <3E84520F.8080809@viasic.com>, Bill Cox says...
>
>Ok, I'll kick in with a very very old point of view on the topic that 
>dates back to the beginning of time...
>
>Operator overloading should not be implemented as methods.  They should 
>be implemented as overloaded functions at the module level.  Then, this 
>whole problem goes away.  Besides, mathematically, a binary operator's 
>operands have equal status.  Why pass one to a method of the other? 
>It's just a stupid trick to try to avoid writing module-level routines.
>
>The fact that we can't even define the == operator without worrying 
>about the LEFT operand being null (but not the right) clearly shows the 
>flaw in C++ style operator overloading.
>
>Bill

I think you are right.  It really makes more sense for the operator overloading
functions to be module level.

From a historical D perspective, I think that the reason they were implemented
as member fuctions instead of module level functions was the issue of accessing
private class members.  This was before everything in a module had public
access.  Now that this is not an issue any more I would certainly be the first
to vote for them to be changed.
March 28, 2003
Re: null == o?
Patrick Down wrote:
> In article <3E84520F.8080809@viasic.com>, Bill Cox says...
> 
>>Ok, I'll kick in with a very very old point of view on the topic that 
>>dates back to the beginning of time...
>>
>>Operator overloading should not be implemented as methods.  They should 
>>be implemented as overloaded functions at the module level.  Then, this 
>>whole problem goes away.  Besides, mathematically, a binary operator's 
>>operands have equal status.  Why pass one to a method of the other? 
>>It's just a stupid trick to try to avoid writing module-level routines.
>>
>>The fact that we can't even define the == operator without worrying 
>>about the LEFT operand being null (but not the right) clearly shows the 
>>flaw in C++ style operator overloading.
>>
>>Bill
> 
> 
> I think you are right.  It really makes more sense for the operator overloading
> functions to be module level.
> 
> From a historical D perspective, I think that the reason they were implemented
> as member fuctions instead of module level functions was the issue of accessing
> private class members.  This was before everything in a module had public
> access.  Now that this is not an issue any more I would certainly be the first
> to vote for them to be changed.

The current setup also allows one to make the comparison method virtual. 
(I'm not sure how useful that is, but it's there)
March 28, 2003
Re: null == o?
You have got to the root of the problem, Bill.

There is no way in D to do an overloaded operator without having a class
member override some specially named member function.  Thus no module-scope
("free") operators are possible.

You're wrong about C++.  It has these.  They are good.  Preferred in fact to
making the binary operator part of the class.

The only reason you'd want a binary operator to be part of a class is if it
needed access to some private section.  In C++ you use friend for this;  in
D you put the operators in the same module as the class.  (but what if the
operator needs private access to *two* classes that are in different
modules?)

We should be able to define free operators:

// example free operator overload

BigInt operator + (BigInt a, BigInt b)
{
   return BigInt.add(a, b);
}

As you can tell I also dislike the current D syntax for declaring operators.
You have to use some specially named member function currently, which means
you have to remember what the name is for each operator you may want to
overload.  I prefer the direct approach;  If I want an operator I do not
want it to have a name.  It just clutters up the namespace and litters it
with landmines;  for instance the above example wouldn't work because member
add is treated specially and would have already overloaded the + operator.

There are some unanswered questions in the D design.

Sean

"Bill Cox" <bill@viasic.com> wrote in message
news:3E84520F.8080809@viasic.com...
> Ok, I'll kick in with a very very old point of view on the topic that
> dates back to the beginning of time...
>
> Operator overloading should not be implemented as methods.  They should
> be implemented as overloaded functions at the module level.  Then, this
> whole problem goes away.  Besides, mathematically, a binary operator's
> operands have equal status.  Why pass one to a method of the other?
> It's just a stupid trick to try to avoid writing module-level routines.
>
> The fact that we can't even define the == operator without worrying
> about the LEFT operand being null (but not the right) clearly shows the
> flaw in C++ style operator overloading.
>
> Bill
>
March 28, 2003
Re: null == o?
Bill, I think you're agreeing with what I'm saying, sort of. I suggested
making the eq() and eqi() methods static simply because I'm not aware of a D
mechanism for doing it outside the class, which is obviously the preferred
approach.

I'm not quite sure what you mean wrt C++. In C++ one can define operator ==
as a class member, or as a free function with or without friend access to
the class. In my opinion (and I think it is the widely accepted preference)
free functions without friend access is the preferred approach. Where's the
flaw?


"Bill Cox" <bill@viasic.com> wrote in message
news:3E84520F.8080809@viasic.com...
> Ok, I'll kick in with a very very old point of view on the topic that
> dates back to the beginning of time...
>
> Operator overloading should not be implemented as methods.  They should
> be implemented as overloaded functions at the module level.  Then, this
> whole problem goes away.  Besides, mathematically, a binary operator's
> operands have equal status.  Why pass one to a method of the other?
> It's just a stupid trick to try to avoid writing module-level routines.
>
> The fact that we can't even define the == operator without worrying
> about the LEFT operand being null (but not the right) clearly shows the
> flaw in C++ style operator overloading.
>
> Bill
>
March 28, 2003
Re: null == o?
"Matthew Wilson" <dmd@synesis.com.au> wrote in message
news:b61875$epf$1@digitaldaemon.com...
> D, like C# and Java, "pretends" that a pointer to an instance is a "thing"
> that can be treated like the instance itself. This is evident in the fact
> that we wish to, and are able to, apply == to references.
>
> This pretence is a dishonesty, one which is obvious when one considers how
> C++ does it. However, when a language does not deal with pointers, the
> dishonesty can be benign and useful.
>
> I don't have a problem with this pretence, so long as it's consistent. If
> you want objects to be treated "like the ints", then you have to do it
> fully. This argument is well worn wrt C++ operator overloading issues, but
> applies all round.
>
> When I write code that compares two entities that are int, I don't have to
> write
>
> int    i1 = . . .
> int    i2 = . . .
>
> if( i1 !== null &&
>     i2 !== null &&
>     i1 == i2)
> {
>
> That would be ludicrous. So why should I have to do it with objects?
Object
> references should either consistently behave as built-ins in expressions,
or
> they should be completely different and require different syntax. This is
> like having one's syntactic convenience without responsibility for caring
> for the syntax. If we can't have that responsibility, then we should
eschew
> the syntactic convenience and just accept that we have to use Object
method
> calls for equivalence comparison and, in that case, for identity also.

I'll argue that value semantics and reference semantics are fundamentally
different, despite having a common syntax. I don't think there's any getting
away from that. Objects are accessed by reference, not by value, and
thinking of them as having value semantics (like ints in your example) just
leads to disaster in many more ways than the behavior of == and === (for
example, consider passing function arguments by value and by reference and
the semantic differences).

> Furthermore, since D has templates - you'll have to bear with me on this
> one, as I'm a real neophyte with D's template syntax - is it not likely
that
> we'd have a template that would work with built-in types and with object
> references. How would this work? Would we have to specialise on the
> built-ins? (What's the point of the template, in that case?) Would we have
> checks against null for the built-ins? (I can't imagine this'd compile,
> would it?) Would we be forced to write it assuming that the references
would
> be non-null, since we would not be able to check for that? It all sounds
> grim.

You can specialize with Object, that way all objects goto one template, and
everything else goes to another, if it turns out to be a problem.
1 2 3 4 5 6
Top | Discussion index | About this forum | D home