'new' class method

Bill Baxter wbaxter at gmail.com
Fri Oct 24 14:38:37 PDT 2008


On Sat, Oct 25, 2008 at 2:04 AM, KennyTM~ <kennytm at gmail.com> wrote:

>>  auto a = Class();  // heap   (default)
>>  auto a = Struct(); // stack   (default)
>>
>>  auto a = Class.new(stack)(); // stack
>>  auto a = Struct.new(stack)(); // stack
>>
>>  auto a = Class.new(heap)(); // heap
>>  auto a = Struct.new(heap)(); // heap
>>
>>   void *addr;
>>   auto a = Class.new(addr)(); // placement
>>   auto a = Struct.new(addr)(); // placement
>>
>
> I strongly *oppose* using stack and heap as keywords because there are also
> (partly irrelevant) data structures called stack and heap, even though
> according to the guideline these class/structs should be named Stack and
> Heap.

Right, that's why both Benji and I proposed making them *context*
keywords.  Just like "Windows" is a keyword only in the context of
extern( ).  This would make heap and stack keywords only in the
context of new(  ).

> And I think we can include the meaning that "scope" attribute always
> allocate on stack (Currently 4 conditions need to be met for so), but I'm
> afraid this may break something (otherwise the other 3 conditions won't be
> there?). Maybe some experts can comment on this?
>

> And I suggest keeping the "new" syntax for heap ("return a pointer")
> allocation. So,

Well, Andrei was looking at getting rid of this "new blah" syntax for
other reasons already, so that's why I tacked in on as a pseudomethod
of classes and structs.

> auto c = Class(...);   // default on heap
> auto s = Struct(...);  // default on stack (compatible with current syntax)
>
> scope c = Class(...);  // on stack
> scope s = Struct(...); // on stack (compatible with current syntax)

The main thing I don't like about this syntax is that it makes it
impossible to create a class temporary on the stack in an expressoin.
It means you always have to declare it and give it a name if you want
to avoid the heap.  It's just not orthogonal in that way.  As in it
entangles construction with declaration, when those two are usually
separate concerns.

Specifically as an example, say you have some object that does
comparisions and you want to pass it to a sort function then uniq it .
  First you wrote this:

     T[] array; ...
     T[] filtered = uniq(sorted(MyComparator.new, array)));

Then you decided the heap alloc was unnecessary there, so now you have
to change it all around

     T[] array; ...
     {   // made a block here so that theComparator goes away after sorting
        scope theComparator = MyComparator.new;
        T[] filtered = uniq(sorted(theComparator, array)));
     }

Instead of just sticking "(stack)" in there and being done with it:

     T[] array; ...
     T[] filtered = uniq(sorted(MyComparator.new(stack), array)));

> auto c = new Class(...);  // on heap (compatible with current syntax)
> auto s = new Struct(...); // on heap (compatible with current syntax)
>
> auto c = new(...) Class(...);  // placement (compatible with current syntax)
> auto s = new(...) Struct(...); // placement (compatible with current
> syntax?)
>
>
> /* if you want symmetry, do it like this:
>
> new c = Class(...);
> new(...) c = Class(...);
> kinda strange for me. */

Yeh, me too.  I definitely don't want any more of this sillyness of
mixing up construction with declaration.

> These will cause minimum change while eliminating the "new" for most cases.
> This won't free the "new" keyword though.

I don't particularly think it needs to be freed up.  A better case may
be made for, delete, though because there's less that's special about
how it works.

>> Yeah! I noticed it. And I like it. In fact, I thought to myself "that's
>> almost the same as my idea".

(To Benji now) Yep, it was!

>> Generally, I'm not a fan of the consecutive
>> sequence of parentheses (especially that templates already make for double
>> parens; I can't imagine I'd want triple parens for a templatized
>> consttructor call).

Well, the idea is that the versions that use "new" will be fairly
rare.  I'm certainly open to other ideas.  I suggested using [] just
for new args in another post.  Like
     MyClass.new[scope](foo,bar)
It just seems odd to me to use that in this one place and no other.  I
think the parens would work, which is why I went back to parens.

Another possibility might be to introduce some syntax for heap vs
stack and only use () for placement new -- like this:

     Class.*new(construct_args);   // stack (like *foo is dereferenced
foo pointer)
     Struct.*new(construct_args);  // stack

     Class.new(construct_args); // heap
     Struct.new(construct_args); // heap

     Class.new@(new_args)(construct_args);  // placement
     Struct.new@(new_args)(construct_args); // placement

>> For non-template chained calls, I'm not quite sure which I prefer:
>>
>>  auto a = Foo.new(heap)(Bar.new(stack)());
>>
>>  auto a = on(heap) Foo(on(stack) Bar());

I think Andrei is gunning to get rid of the dangling prefix words in
the grammar.  That's why I put .new at the end.  I think he would also
be happy with a regular function-like syntax, too, but what I've seen
of that looks ugly.  When you do 'new' there always a class or struct
involved, so why not make it a pseudo property of every class and
struct, just like .init or .tupleof?

--bb



More information about the Digitalmars-d mailing list