July 13, 2004
On Tue, 13 Jul 2004 11:45:15 +0000 (UTC), Arcane Jill <Arcane_member@pathlink.com> wrote:

> In article <opsa2m9oo15a2sq9@digitalmars.com>, Regan Heath says...
>>
>> I think you'll find if you read *my* reply to *my* post to which you are
>> replying below you'll find that I rescinded my comment as I realised I had
>> indeed missed the word 'static'.
>
> Yeah I know. Whoops. <embarrassed>. Sometimes I'm just too impatient to read the
> whole list before posting anything.

I know the feeling.

>> You make a good point about what goes on when someone uses a static opCall
>> to emulate a constructor. I agree structs should have constructors. If
>> they have constructors I think they should also have destructors.
>
> Er... WHOA. They can't. That's just not possible in the D framework.

I think I need a tutorial on how they work then, cos I can't see the problem.

> And if you
> keep suggesting this all it means is that Walter will never give us
> CONstructors, which is a much more important priority.

My impression is that Walter considers each suggestion on it's own merits, he won't throw out one idea simply because it's suggested along with another, at least that is how he seems to me.

>> Thus allowing you to write your BigInt stuff with structs,
>
> The class is called Int.

I was not attempting to refer to the class name, I was attempting to refer to the idea.

>> which IMO they should be, as they're value types, not reference types.
>
> They are immutable reference types, and I am perfectly happy with this. If you
> have an Int with a million digits, why on Earth would you want to copy that
> around by VALUE? (Ints can get indefinitely large. It's part of their
> definition).

That makes sense.

> I have no complaints about the struct/class distinction, and I'm happy for Int
> to be a class. Everything works fine, right now (minor bugs aside). I don't wish
> to change it to a struct, thank you very much.
>
>
>
>> I also think structs should have inheritance. NOT in the same way as
>> classes, NOT with any virtual function overhead, simply inherit methods
>> and members. Sure, you can do this with mixins, but IMO they are messy,
>> whereas struct inheritance could be quite clean.
>
> You could always just name the first member variable "sooper". :-)

Walter suggested something like that. You end up with something like...

struct A
{
  void foo()
  {
    *this = A.init;
  }
}

struct B
{
  alias A.foo foo;

  int bar = 5;
  A a;
}

struct C
{
  alias B.foo foo;
  alias B.bar bar;

  B b;
}

void main()
{
  C c;
  c.bar = 1;
  c.foo();
  printf("%d\n",c.bar);
}

basically an alias for every member in every struct you derive from. With complex structs this gets out of hand.

When you run the above code the line *this = A.init sets the int bar to 0, I would have thought it would have left it un-changed.

> Have you considered that instead of wishing all this extra functionality on a
> struct, you could just use a class?

Yeah.. but structs have this wonderful ability to allow you to go..

struct A
{
  void foo()
  {
    *this = A.init;
  }
}

class B
{
  int a = 5;
  int b = 6;

  void foo()
  {
    *this = B.init; //error: can only * a pointer, not a 'B'
    this = B.init; //appears to do nothing
  }
}

void main()
{
  B b = new B();
  b.a = 1;
  b.b = 2;
  b.foo();
  printf("%d %d\n",b.a,b.b);
}

I found this when writing the Hashing algorithms, I wanted to use structs for the above and other reasons. The current code in deimos uses structs, it's not perfect, it needs a few tweaks.

After writing it, I wrote a few of them as classes, I am un-decided which is better.

> You seem to be locked into this "value
> semantics therefore MUST be a struct" mentality, but that's not the only
> solution. D structs are simply lightweight aggregates. Treat them as such, and
> use classes if you want more.

I can but give it a go.

> It's really only the intialization of structs that (most) people are complaining
> about.

Regan.

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 13, 2004
On Tue, 13 Jul 2004 10:16:36 -0700, Daniel Horn wrote:

> Derek Parnell wrote:
>> On Tue, 13 Jul 2004 18:21:23 +1000, Matthew Wilson wrote:
>> 
>> [snip]
>> 
>>>>But I see "<<=" as a way of
>>>>saying 'copy the value on the right-side to the thing that's on the
>>>>left-side'.  Gee, much like I see "=" really. Sure wish I could overload
>>>>"=", 'cos that would make a lot of sense to me.
>>>>
>>>>I want to set the value of these structures but I don't want to deal with the internal repesentation all the time. That's why we have method's, right?
>>>>
>>>>
>>>>Am I doing things the kosher 'D' way or am I way off base?
>>>
>>>It seems like one of these things that is convenient to its author (at the time of writing - you'll be confused by it in six months' time) but is likely to lead to a host of inconsistent behaviours amongst the practitioners.
>>>
>>>So I'd say "way off base", I'm afraid
>> 
>> Thanks mate. I sorta suspected so. Now if only I could overload '=' so my INTENTIONS to the code reader were a bit more obvious.
>> 
>> So what's a better way? An explicit function call to assign a value?
>> 
>> eg.
>> 
>>    a.opAssign("hello")
>> 
>> It sort of seems stupid to resort to doing this when the language already has an operator to do it...
>> 
> I'm all for overloading <<=
> or else adding some sort of new operator like <-  for "deep copy"

Hmmmmm... the 'deep copy' operator sounds like I decent idea.

-- 
Derek
Melbourne, Australia
14/Jul/04 9:28:22 AM
July 14, 2004
In article <opsa3juaum5a2sq9@digitalmars.com>, Regan Heath says...

>>> You make a good point about what goes on when someone uses a static
>>> opCall
>>> to emulate a constructor. I agree structs should have constructors. If
>>> they have constructors I think they should also have destructors.
>>
>> Er... WHOA. They can't. That's just not possible in the D framework.
>
>I think I need a tutorial on how they work then, cos I can't see the problem.

When a return statement is executed to leave a function, or a break statement is executed to leave a statement block, or a goto is executed, things go out of scope. When that happens in C++, destructors are called. In D, however, destructors are NOT called. (There is an exception to this rule - auto classes. I would imagine (though I don't know for sure) that these are implemented with some kind of invisible try/catch substitute).

For D structs, this is perfectly fine, since D structs don't have destructors.

For D classes, this is also fine, because those objects still exist on the heap. THEIR destructors will be called later, eventually, when the garbage collector gets around to it.

So, to unwind the stack, all you have to do is reassign the stack pointer. (It's slightly more complicated in the event of an exception, but exceptions are supposed to be rare).

If "things-which-were-stored-on-the-stack" were allowed destructors, this simple model would have to change quite drastically. Essentially, every struct would have to be auto! I imagine it would have to be quite a rewrite of D.

Now, you might say, "why not store structs on the heap?. Of course, the problem would then go away. Well, can can store structs on the heap already (like this:)

#    MyStruct[] s = new MyStruct[1];

but you still can't give it a destructor, because there is still nothing to stop some other user from doing:

#    MyStruct s;

If you want ALL structs to be stored on the heap, then that, again, would involve a rewrite of D (and the distinction between struct and class would start to disappear).




>> And if you
>> keep suggesting this all it means is that Walter will never give us
>> CONstructors, which is a much more important priority.
>
>My impression is that Walter considers each suggestion on it's own merits, he won't throw out one idea simply because it's suggested along with another, at least that is how he seems to me.

Perhaps, but Walter is on record (on this forum) as saying that he will consider giving us constructors for structs providing we can live without destructors, non-bitwise copying and inheritance. I don't want to give him the impression that we can't.



>Yeah.. but structs have this wonderful ability to allow you to go..
>
>struct A
>{
>   void foo()
>   {
>     *this = A.init;
>   }
>}

Ah yes. That's completely true. It's curious that you can't do that with classes, and I can't quite see why it should be disallowed. Still, it's not really TOO hard to do this the long way round in classes, like this:

#    class A
#    {
#        void foo()
#        {
#            memberVariable1 = T1.init;
#            memberVariable2 = T2.init;
#            memberVariable3 = T3.init;
#            // ...
#        }
#    }

Arcane Jill



July 14, 2004
On Wed, 14 Jul 2004 07:29:36 +0000 (UTC), Arcane Jill <Arcane_member@pathlink.com> wrote:
> In article <opsa3juaum5a2sq9@digitalmars.com>, Regan Heath says...
>
>>>> You make a good point about what goes on when someone uses a static
>>>> opCall
>>>> to emulate a constructor. I agree structs should have constructors. If
>>>> they have constructors I think they should also have destructors.
>>>
>>> Er... WHOA. They can't. That's just not possible in the D framework.
>>
>> I think I need a tutorial on how they work then, cos I can't see the
>> problem.
>
> When a return statement is executed to leave a function, or a break statement is
> executed to leave a statement block, or a goto is executed, things go out of
> scope. When that happens in C++, destructors are called. In D, however,
> destructors are NOT called. (There is an exception to this rule - auto classes.
> I would imagine (though I don't know for sure) that these are implemented with
> some kind of invisible try/catch substitute).
>
> For D structs, this is perfectly fine, since D structs don't have destructors.
>
> For D classes, this is also fine, because those objects still exist on the heap.
> THEIR destructors will be called later, eventually, when the garbage collector
> gets around to it.
>
> So, to unwind the stack, all you have to do is reassign the stack pointer. (It's
> slightly more complicated in the event of an exception, but exceptions are
> supposed to be rare).
>
> If "things-which-were-stored-on-the-stack" were allowed destructors, this simple
> model would have to change quite drastically. Essentially, every struct would
> have to be auto! I imagine it would have to be quite a rewrite of D.
>
> Now, you might say, "why not store structs on the heap?. Of course, the problem
> would then go away. Well, can can store structs on the heap already (like this:)
>
> #    MyStruct[] s = new MyStruct[1];
>
> but you still can't give it a destructor, because there is still nothing to stop
> some other user from doing:
>
> #    MyStruct s;
>
> If you want ALL structs to be stored on the heap, then that, again, would
> involve a rewrite of D (and the distinction between struct and class would start
> to disappear).

Thanks. I'll take my time digesting all this.

>>> And if you
>>> keep suggesting this all it means is that Walter will never give us
>>> CONstructors, which is a much more important priority.
>>
>> My impression is that Walter considers each suggestion on it's own merits,
>> he won't throw out one idea simply because it's suggested along with
>> another, at least that is how he seems to me.
>
> Perhaps, but Walter is on record (on this forum) as saying that he will consider
> giving us constructors for structs providing we can live without destructors,
> non-bitwise copying and inheritance. I don't want to give him the impression
> that we can't.

Sure.

>> Yeah.. but structs have this wonderful ability to allow you to go..
>>
>> struct A
>> {
>>   void foo()
>>   {
>>     *this = A.init;
>>   }
>> }
>
> Ah yes. That's completely true. It's curious that you can't do that with
> classes, and I can't quite see why it should be disallowed.

Good point. I'll create a new post asking this.

> Still, it's not
> really TOO hard to do this the long way round in classes, like this:
>
> #    class A
> #    {
> #        void foo()
> #        {
> #            memberVariable1 = T1.init;
> #            memberVariable2 = T2.init;
> #            memberVariable3 = T3.init;
> #            // ...
> #        }
> #    }

Until the class becomes large and/or you forget to add lines for newly added members.. etc.

Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
1 2 3 4 5 6 7
Next ›   Last »