| Thread overview | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 07, 2009 important proposal: scope keyword for class members | ||||
|---|---|---|---|---|
| ||||
I'd like to propose a new use for the 'scope' keyword within an aggregate body.
Members of class type declared with the scope keyword are allocated not as references or pointers, but initialized directly inside the container. Instead of a default initializer of 'null', it will initialize with the default constructor of the class, or an optional assignment after the declaration. Any 'new [type]' within the assignment will resolve to a simple call to the type's __ctor, instead of a memory allocation.
Example:
class Inner {
this() {}
this(int x) {}
}
class Container {
Inner i1; // initialized to null
scope Inner i2; // allocated within class
scope i3 = new Inner(42); // allocated within class
this() {
// implicit i2.__ctor();
// i3.__ctor(42) written above, executed here
assert(i1 is null);
assert(i2 !is null);
i1 = new Inner;
}
this(int overloaded) {
// i2 and i3 are constructed, same as above
}
~this() {
// implicit i2.__dtor();
// implicit i3.__dtor();
// i1 is still somewhere in the heap
}
}
IN ENGLISH:
If it's likely that class members will be constructed with and die with the object, why not just allocate them right in the class? Save on heap fragmentation and cache misses. I was honesetly flabberghasted when I realized there was no way to do this in D, it seems like it should be one of the most basic constructs of a C-derived (or any low-ish level) language.
The programmer knows best where he wants his objects stored. Also, the 'scope' makes sense, and we should mirror the current behavior of the keyword in function bodies.
| ||||
March 07, 2009 Re: important proposal: scope keyword for class members | ||||
|---|---|---|---|---|
| ||||
Posted in reply to John Simon | == Quote from John Simon (zildjohn01@gmail.com)'s article > I'd like to propose a new use for the 'scope' keyword within an aggregate body. Members of class type declared with the scope keyword are allocated not as references or pointers, but initialized directly inside the container. Instead of a default initializer of 'null', it will initialize with the default constructor of the class, or an optional assignment after the declaration. Any 'new [type]' within the assignment will resolve to a simple call to the type's __ctor, instead of a memory allocation. > Example: > class Inner { > this() {} > this(int x) {} > } > class Container { > Inner i1; // initialized to null > scope Inner i2; // allocated within class > scope i3 = new Inner(42); // allocated within class > this() { > // implicit i2.__ctor(); > // i3.__ctor(42) written above, executed here > assert(i1 is null); > assert(i2 !is null); > i1 = new Inner; > } > this(int overloaded) { > // i2 and i3 are constructed, same as above > } > ~this() { > // implicit i2.__dtor(); > // implicit i3.__dtor(); > // i1 is still somewhere in the heap > } > } > IN ENGLISH: > If it's likely that class members will be constructed with and die with the object, why not just allocate them right in the class? Save on heap fragmentation and cache misses. I was honesetly flabberghasted when I realized there was no way to do this in D, it seems like it should be one of the most basic constructs of a C-derived (or any low-ish level) language. > The programmer knows best where he wants his objects stored. Also, the 'scope' makes sense, and we should mirror the current behavior of the keyword in function bodies. But the whole point of classes is that they're supposed to be polymorphic. If you don't need polymorphism, that's what structs are for. You can store them either inline (default) or in separate heap space (using pointers). If you do need polymorphism, you don't know at compile time what the size of the object is supposed to be, and initializing the object the way you suggest defeats polymorphism. | |||
March 07, 2009 Re: important proposal: scope keyword for class members | ||||
|---|---|---|---|---|
| ||||
Posted in reply to dsimcha | dsimcha wrote:
> But the whole point of classes is that they're supposed to be polymorphic. If you
> don't need polymorphism, that's what structs are for. You can store them either
> inline (default) or in separate heap space (using pointers). If you do need
> polymorphism, you don't know at compile time what the size of the object is
> supposed to be, and initializing the object the way you suggest defeats polymorphism.
scope can't use polymorphism. It's for situations in which you need your polymorphic type to be on the stack for whatever reason, but you don't need polymorphism at the moment.
For example, you want to open a file. File inherits from some sort of Stream class; it's not a struct. So you can write:
auto file = new File(path);
scope(exit) file.close;
Or:
scope file = new File(path);
| |||
March 07, 2009 Re: important proposal: scope keyword for class members | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | Christopher Wright Wrote:
> dsimcha wrote:
> > But the whole point of classes is that they're supposed to be polymorphic. If you
> > don't need polymorphism, that's what structs are for. You can store them either
> > inline (default) or in separate heap space (using pointers). If you do need
> > polymorphism, you don't know at compile time what the size of the object is
> > supposed to be, and initializing the object the way you suggest defeats polymorphism.
>
> scope can't use polymorphism. It's for situations in which you need your polymorphic type to be on the stack for whatever reason, but you don't need polymorphism at the moment.
>
> For example, you want to open a file. File inherits from some sort of Stream class; it's not a struct. So you can write:
>
> auto file = new File(path);
> scope(exit) file.close;
>
> Or:
> scope file = new File(path);
Exactly. And on top of that, how does being 'scope' limit its polymorphism? Code time:
int main(char[][] args) {
class A {}
class B : A {}
class C : B {}
void tryB(A a) {writefln(cast(B)a ? "casted" : "null");}
scope a = new A;
scope b = new B;
assert(cast(C)b is null); // OK
assert(cast(A)b == b); // OK
tryB(a); // "null"
tryB(b); // "casted"
return 42;
}
You can always upcast and downcast safely, since it isn't actually a 'value' type, only the address is passed around. The type of the class remains intact.
So I don't see why this shouldn't be extended to classes as aggregate members.
| |||
March 07, 2009 Re: important proposal: scope keyword for class members | ||||
|---|---|---|---|---|
| ||||
Posted in reply to John Simon | John Simon wrote:
> I'd like to propose a new use for the 'scope' keyword within an aggregate body.
>
> Members of class type declared with the scope keyword are allocated not as references or pointers, but initialized directly inside the container. Instead of a default initializer of 'null', it will initialize with the default constructor of the class, or an optional assignment after the declaration. Any 'new [type]' within the assignment will resolve to a simple call to the type's __ctor, instead of a memory allocation.
A while back, Walter said that he planned to do exactly this. I'm not sure what the timetable is though, or if plans have changed.
| |||
March 07, 2009 Re: important proposal: scope keyword for class members | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote:
> John Simon wrote:
>> I'd like to propose a new use for the 'scope' keyword within an aggregate body.
>>
>> Members of class type declared with the scope keyword are allocated not as references or pointers, but initialized directly inside the container. Instead of a default initializer of 'null', it will initialize with the default constructor of the class, or an optional assignment after the declaration. Any 'new [type]' within the assignment will resolve to a simple call to the type's __ctor, instead of a memory allocation.
>
> A while back, Walter said that he planned to do exactly this. I'm not sure what the timetable is though, or if plans have changed.
Oh, I should mention that I'm not sure how the compiler would handle this scenario:
class A { byte[16]; }
class B { byte[32]; }
class C {
this( bool b ) {
if( b ) o = new A;
else o = new B;
}
scope Object o;
}
If I had to guess I'd say that the compiler would either reserve the max size necessary to store both A or B, or that in non-trivial cases it just wouldn't bother with reserving space for o at all.
| |||
March 07, 2009 Re: important proposal: scope keyword for class members | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote:
> John Simon wrote:
>> I'd like to propose a new use for the 'scope' keyword within an aggregate body.
>>
>> Members of class type declared with the scope keyword are allocated not as references or pointers, but initialized directly inside the container. Instead of a default initializer of 'null', it will initialize with the default constructor of the class, or an optional assignment after the declaration. Any 'new [type]' within the assignment will resolve to a simple call to the type's __ctor, instead of a memory allocation.
>
> A while back, Walter said that he planned to do exactly this. I'm not sure what the timetable is though, or if plans have changed.
I'd be happier if we investigated scope in classes as an ownership mechanism. In-situ storage is nice, but ownership management is more important.
Andrei
| |||
March 07, 2009 Re: important proposal: scope keyword for class members | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Andrei Alexandrescu wrote:
> Sean Kelly wrote:
>> John Simon wrote:
>>> I'd like to propose a new use for the 'scope' keyword within an aggregate body.
>>>
>>> Members of class type declared with the scope keyword are allocated not as references or pointers, but initialized directly inside the container. Instead of a default initializer of 'null', it will initialize with the default constructor of the class, or an optional assignment after the declaration. Any 'new [type]' within the assignment will resolve to a simple call to the type's __ctor, instead of a memory allocation.
>>
>> A while back, Walter said that he planned to do exactly this. I'm not sure what the timetable is though, or if plans have changed.
>
> I'd be happier if we investigated scope in classes as an ownership mechanism. In-situ storage is nice, but ownership management is more important.
Yeah, in-situ storage would just be a QOI feature like it is for scope variables at function level. I agree that the logical effect of scope at class level is more important.
| |||
March 07, 2009 Re: important proposal: scope keyword for class members | ||||
|---|---|---|---|---|
| ||||
Posted in reply to John Simon | John Simon wrote:
> You can always upcast and downcast safely, since it isn't actually a 'value' type, only the address is passed around. The type of the class remains intact.
Right, but a scope variable has its type decided at compile time, always. In that way, it's not polymorphic.
| |||
March 07, 2009 Re: important proposal: scope keyword for class members | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote: > Andrei Alexandrescu wrote: >> Sean Kelly wrote: >>> John Simon wrote: >>>> I'd like to propose a new use for the 'scope' keyword within an aggregate body. >>>> >>>> Members of class type declared with the scope keyword are allocated not as references or pointers, but initialized directly inside the container. Instead of a default initializer of 'null', it will initialize with the default constructor of the class, or an optional assignment after the declaration. Any 'new [type]' within the assignment will resolve to a simple call to the type's __ctor, instead of a memory allocation. >>> >>> A while back, Walter said that he planned to do exactly this. I'm not sure what the timetable is though, or if plans have changed. >> >> I'd be happier if we investigated scope in classes as an ownership mechanism. In-situ storage is nice, but ownership management is more important. > > Yeah, in-situ storage would just be a QOI feature like it is for scope variables at function level. I agree that the logical effect of scope at class level is more important. You're talking about something like this? class A { scope Object o; this () { o = new Object; } } converts to: class A { Object o; this () { void* ptr = gc.allocAndIgnore(Object.classinfo.size); o = new(ptr) Object; } ~this () { delete o; } } | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply