September 01, 2004
I think that your post is a good summary of many of the great features about D.  And in the past, I agreed with you: let's do away with pointers in favor of more automatic and safe constructs.  I still think that way, at the semantic level.  I'm not suggesting that it should be possible to do pointer arithmetic on class references, or anything funky like that.

But did you read my original post (the one that started this thread)? I've come across a few reasons - that IMHO are fairly compelling - why class references should use pointer syntax.  What do you think about those reasons?

September 01, 2004
On Wed, 01 Sep 2004 10:49:37 -0700, Russ Lewis <spamhole-2001-07-16@deming-os.org> wrote:
> I think that your post is a good summary of many of the great features about D.  And in the past, I agreed with you: let's do away with pointers in favor of more automatic and safe constructs.  I still think that way, at the semantic level.  I'm not suggesting that it should be possible to do pointer arithmetic on class references, or anything funky like that.
>
> But did you read my original post (the one that started this thread)? I've come across a few reasons - that IMHO are fairly compelling - why class references should use pointer syntax.  What do you think about those reasons?

Here are your reasons again, and my thoughts on them:

> 1) Templates
> The first one I remember coming across was template code.  Say you want to work with something by reference.  If the thing is a class, then you must use the syntax "T foo" while if it is anything else, you must use the syntax "T* foo".  It would be better if there was consistency.  If there is an '*', then it is a pointer to something.  If there is not, then it is a literal variable.

I agree, this is confusing, annoying and causes subtle bugs. I once changed the type used in a template from a class to a struct and created a bug, that took me 1/2 an hour to find.

That said, I *like* the fact that we have 2 different types of object, one value type stack allocated object, and one reference type heap allocated (generally) object.

Walter has added the ability for you to specify which types can be used in your templates, so, a well written template does not suffer from this problem any more.

I suggested a little while back that modifying an 'in' parameter should be an error, if this were adopted then the compiler would have spotted the bug I created switching from a class to a struct, and most(all?) the bugs created by the differences using struct/class in templates.

Basically I think the 2 different types are a good thing, and we can catch the bad things they can potentially cause.

> 2) Newbie learning curve
> Many people have posted questions on the newsgroup, asking why their code segfaults when they write code like this:
> 	MyClass foo;
> 	foo.DoStuff();

I believe the compiler could be improved to spot this obvious error, in which case this is no longer a problem.

> We don't know how many more people just got turned off to D and never asked the question here.  If the '*' were required, then newbies would learn quickly that the right thing to do is:
> 	MyClass *foo = new MyClass;
> 	foo.DoStuff();

> 3) Objects on Heap
> We've had many long discussions about objects on the heap.  The fact that D lacked them lead to 'auto' variables, and still people want more.   Frankly, I think that objects on the heap make a lot of sense sometimes;  we could have them and still avoid the copy constructor stuff.

We already have objects on the heap, via structs and 'auto' classes, and they work as you'd want them to work, I see no problem here.

Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
September 02, 2004
>> So, assuming that they *are* different, why is it a benefit that, when you declare a pointer to one you use the '*', and when you declare a pointer to the other, you don't?
>
>You don't declare a *pointer* to the other, just that other is a reference type! What is so hard about that? Like, if you pass an array you don't call it "pointer to an array with external length"... This is definately a point of view thing, but i'd say people thinking in "pointer to a class" (instead of "class is a pointer to underlying struct") are just spoiled by the thinking one certain language forces on its users, while *all* of the other languages i'm aware of (Delphi, Java, C#, even Sather) use the other one and their users don't complain!

Perhaps I'm wrong, but that's not the point.
We talked about templates which are hard to maintain because the same synthax
has different meanings but templates are about writing general code, that can be
used everywhere.

This thread was only about a suggestion to make the language mor consistent. I don't realy like this idea, but it is still a way to solve the problems that you have when you write template-code.


Perhaps we wouldhave needed a different synthax way before. But I think now it's to late for big changes.

We could have done something like this:

"name" means the value of something, "&name" means the address of something. So to do a value-assignment you write "name1 = name2", to do a reference-assignment you write "&name1 = &name2". On a value-type "&name" is just constant, so you can't assign a new adress, while it's mutable on reference-objects.

This way we would have a very consistent notation.

ValueType vtFoo, vtBar;
ReferenceType rtFoo, rtBar;

vtFoo = vtBar; // value-assignemtn
&vtFoo = &vtBar; // impossible, &vtFoo isn't an l-value

rtFoo = rtBar; // not sure, eigther this isn't allowed or we'd need a opAssign,
which would be very constent to havving +=, -=. *=, ... overloadable
&rtFoo = &rtBar; // reference-assignment


This way the same notation would allways refere to the same thing, so writing template code would be very easy.


-- Matthias Becker


September 02, 2004
In article <ch523h$2etg$2@digitaldaemon.com>, Russ Lewis says...
>
>But did you read my original post (the one that started this thread)? I've come across a few reasons - that IMHO are fairly compelling - why class references should use pointer syntax.  What do you think about those reasons?

Good call, I'm sorry about that.  Let me rectify this situation:

1) Templates

I don't understand the practical implications of the problem you point out.  The fact that objects have implicit reference semantics and structs don't doesn't seem to cause any tangible woes.  I think that if the distinction was indeed problematic, it would have been discovered long ago in C++ since arrays and char/int/etc. have a similar distinction.  Can you post a link to an example that demonstrates this problem?  Length isn't an issue.

Regardless, even if there are situations where the different semantics cause a problem in the context of templates, I'd wager that they are very few in number, and infinitesimal in a relative sense.  Now that D can specify which types are allowable in a template, such exceptional circumstances can be handled.  It's obviously not a perfect method, but I believe it is optimal.  It's best to make those scenarios which represent 99% of use cases easier at the expense of the 1% fringe than vice versa.  (Although it does frost my cherries when I happen to find myself in that 1% :-)

2) Newbie learning curve

The compiler should flag this as an error, plain and simple.

On a similar note, I've been giving this some more thought, and I really think that having the 'in' keyword designate strict enforcement (changing the variable is an error) is The Right Thing.  That, combined with encouraging new programmers to *always* specify in, out, or inout should mask the confusion of implicit/explicit reference semantics completely.  If the in keyword is omitted, then things can behave as usual to prevent the frustration of experienced users.

3) Objects on the [Stack]

I think the combination of the 'auto' keyword and garbage collection obviate the need for this; there simply isn't any benefit.



September 02, 2004
On Thu, 2 Sep 2004 16:06:06 +0000 (UTC), ninjadroid <ninjadroid_member@pathlink.com> wrote:
> In article <ch523h$2etg$2@digitaldaemon.com>, Russ Lewis says...
> 1) Templates
>
> I don't understand the practical implications of the problem you point out.  The fact that objects have implicit reference semantics and structs don't doesn't seem to cause any tangible woes.  I think that if the distinction was indeed problematic, it would have been discovered long ago in C++ since arrays and char/int/etc. have a similar distinction.  Can you post a link to an example that demonstrates this problem?  Length isn't an issue.

Here is a simplified example showing what I personally encountered:

template t(T) {
  void change(T a) {
    a.prop++;
  }
}

class  A { int prop; }
struct B { int prop; }

void main()
{
  A a = new A();
  B b;

  //a.prop == 0
  t!(A).change(a);
  //a.prop now == 1

  //b.prop == 0
  t!(B).change(b);
  //b.prop now == 0;
}

of course this is simplified and it's easy to see what is happening, the real case was much more complicated.

That said, I think template specialisation solves this problem eg.

template t(T : class) {
  void change(T a) {
    a.prop++;
  }
}

does the above allow you to use it with other 'reference' types eg the built in arrays? if not perhaps a 'value' or 'reference' keyword in template specialisation would be nice eg.

template t(T : reference) {
  void change(T a) {
    a.prop++;
  }
}

Another solution is to change the template to

template t(T) {
  void change(inout T a) {
    a.prop++;
  }
}

in other words pass the struct by reference.

I believe checking 'in' parameters are not modified would have spotted this bug for me, I still advocate this change.

Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
September 02, 2004
On Thu, 2 Sep 2004 14:45:00 +0000 (UTC), Matthias Becker <Matthias_member@pathlink.com> wrote:
>>> So, assuming that they *are* different, why is it a benefit that, when
>>> you declare a pointer to one you use the '*', and when you declare a
>>> pointer to the other, you don't?
>>
>> You don't declare a *pointer* to the other, just that other is a
>> reference type! What is so hard about that? Like, if you pass an array
>> you don't call it "pointer to an array with external length"... This is
>> definately a point of view thing, but i'd say people thinking in
>> "pointer to a class" (instead of "class is a pointer to underlying
>> struct") are just spoiled by the thinking one certain language forces on
>> its users, while *all* of the other languages i'm aware of (Delphi,
>> Java, C#, even Sather) use the other one and their users don't complain!
>
> Perhaps I'm wrong, but that's not the point.
> We talked about templates which are hard to maintain because the same synthax
> has different meanings but templates are about writing general code, that can be
> used everywhere.
>
> This thread was only about a suggestion to make the language mor consistent. I
> don't realy like this idea, but it is still a way to solve the problems that you
> have when you write template-code.

So you don't think template specialisation solves them?

It just occured to me that "specialisation" is almost the opposite of "generic", and D's solution (C/C++ also) to the "generic" problem is to be less generic.

Perhaps this is a bad thing, or perhaps it's the natural result of having 'different' types which simply cannot be treated 'generically'. You could wrap all the native types in classes, then you would have a bunch of types you could treat generically.

It seems to me that is what is required to enable truly generic programming. That and perhaps a less strict type sort of language.

Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
September 02, 2004
In article <opsdp0visx5a2sq9@digitalmars.com>, Regan Heath says...
>
>Perhaps this is a bad thing, or perhaps it's the natural result of having 'different' types which simply cannot be treated 'generically'. You could wrap all the native types in classes, then you would have a bunch of types you could treat generically.

Perhaps we should just all use Smalltalk ;)

>It seems to me that is what is required to enable truly generic programming. That and perhaps a less strict type sort of language.

I'll admit I'm not entirely comfortable with the reference semantics for class obejcts in D, but I don't know that there's an easy fix on the language side. What I will probably end up doing is use a bunch of little utility templates that are specialized to guarantee expected behavior.  However I think classes are the odd man out in this case.  Arrays may use references but they have COW semantics, while classes do not.

In some respects it would be kind of interesting to have the language support limited COW semantics for classes as well.  Perhaps call a copy ctor if a "watched" (ie. non-const) member function is called on a shared object.  So you could declare a class this way:

# class COWClass {
# public:
#    int getValue();
#    watched void setValue( int v );
# }

Frankly, I'm not sure how useful this would be, but I thought I'd mention it anyway as it's not something I've seen in a language before.


Sean


September 02, 2004
In article <opsdpz09y05a2sq9@digitalmars.com>, Regan Heath says...
>
>Another solution is to change the template to
>
>template t(T) {
>   void change(inout T a) {
>     a.prop++;
>   }
>}
>
>in other words pass the struct by reference.
>
>I believe checking 'in' parameters are not modified would have spotted this bug for me, I still advocate this change.

That strikes me as the closest you're gonna get to The Right Thing.  I also think it solidifies the case for strictly enforcing in parameters!  Is there any reason not to?


September 03, 2004
Sean Kelly wrote:
> I'll admit I'm not entirely comfortable with the reference semantics for class
> obejcts in D, but I don't know that there's an easy fix on the language side.
> What I will probably end up doing is use a bunch of little utility templates
> that are specialized to guarantee expected behavior.

Perhaps a template called ReferenceTo() or PointerTo() which gives the reference type for any given type?

1 2 3
Next ›   Last »