www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Auto syntax revisited

reply Fredrik Olsson <peylow gmail.com> writes:
After some discussion on #d I though why not put my thoughts into more 
permanent writing.

Keyword auto is used for two reasons; implicit type and making sure the 
object is destroyed when going out of scope. I suggest a new keyword for 
the latter: local.

local auto foo = new Bar();

Why? First of auto is only used for the implicit type, so no confusion. 
  The keyword local in itself describes pretty to the point what is 
supposed to happen with the variable. And nothing is said about the 
stack, so we are future proof if in the future we would like to also have:

local auto foo = Bar();

Where Bar(); is a function returning an Object, but we still want the 
object to be destructed when going out of this scope. The implementation 
is quite different as the Object would need to be on heap, but the 
syntax is the same. So local would indicate what should be done (destroy 
when out of scope), not how it should be done (allocate on stack or 
whatever).

Even this could be possible, without syntax changes:
{
   local Foo bar;
   // some code
   Baz(bar); // Jupp Baz have a inout parameter returning an object.
} // And bar is still destroyed if set to something here...


regards
// Fredrik Olsson
Feb 20 2006
next sibling parent "Derek Parnell" <derek psych.ward> writes:
On Tue, 21 Feb 2006 07:23:26 +1100, Fredrik Olsson <peylow gmail.com>  
wrote:

 After some discussion on #d I though why not put my thoughts into more  
 permanent writing.

 Keyword auto is used for two reasons; implicit type and making sure the  
 object is destroyed when going out of scope. I suggest a new keyword for  
 the latter: local.
Its got my vote. A much better idea that having 'auto' overloaded. -- Derek Parnell Melbourne, Australia
Feb 20 2006
prev sibling next sibling parent Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Fredrik Olsson wrote:
 After some discussion on #d I though why not put my thoughts into more 
 permanent writing.
 
 Keyword auto is used for two reasons; implicit type and making sure the 
 object is destroyed when going out of scope. I suggest a new keyword for 
 the latter: local.
 
 local auto foo = new Bar();
 
 Why? First of auto is only used for the implicit type, so no confusion. 
  The keyword local in itself describes pretty to the point what is 
 supposed to happen with the variable. And nothing is said about the 
 stack, so we are future proof if in the future we would like to also have:
 
 local auto foo = Bar();
 
 Where Bar(); is a function returning an Object, but we still want the 
 object to be destructed when going out of this scope. The implementation 
 is quite different as the Object would need to be on heap, but the 
 syntax is the same. So local would indicate what should be done (destroy 
 when out of scope), not how it should be done (allocate on stack or 
 whatever).
 
 Even this could be possible, without syntax changes:
 {
   local Foo bar;
   // some code
   Baz(bar); // Jupp Baz have a inout parameter returning an object.
 } // And bar is still destroyed if set to something here...
 
 
 regards
 // Fredrik Olsson
What ever the final syntax/semantics may be, a new keyword is a better solution.
Feb 20 2006
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
Fredrik Olsson wrote:
 After some discussion on #d I though why not put my thoughts into more 
 permanent writing.
 
 Keyword auto is used for two reasons; implicit type and making sure the 
 object is destroyed when going out of scope. I suggest a new keyword for 
 the latter: local.
 
 local auto foo = new Bar();
If we're moving towards stack-based auto classes then I'd prefer the distinction be associated with the object and not the reference. ie. auto foo = local Bar(); I think the distinction is important because foo can be reassigned to a non-local object. Alternately, simply omitting 'new' entirely might be feasible, though the meaning there is less obvious. As I said in #d: Foo Bar() { return new Foo(); } auto foo = Bar(); looks like a stack-based initialization even though it's not. But perhaps it doesn't matter in this case, as nothing will break if a heap-based instance is used in place of a stack-based instance, it's replacing things the other direction that can cause problems. Sean
Feb 20 2006
next sibling parent reply "Charles" <noone nowhere.com> writes:
 auto foo = local Bar();
This gets my vote , but why is everyone using 'auto' ( deduction )keyword here, gets a little confusing since you're trying to replace the other auto with local. ( For people not in on the #d discussion ). MyClass foo = local MyClass("parameters"); yes ? So 'local' replaces 'new' for stack based allocations. "Sean Kelly" <sean f4.ca> wrote in message news:dtdb2e$2lsp$1 digitaldaemon.com...
 Fredrik Olsson wrote:
 After some discussion on #d I though why not put my thoughts into more
 permanent writing.

 Keyword auto is used for two reasons; implicit type and making sure the
 object is destroyed when going out of scope. I suggest a new keyword for
 the latter: local.

 local auto foo = new Bar();
If we're moving towards stack-based auto classes then I'd prefer the distinction be associated with the object and not the reference. ie. auto foo = local Bar(); I think the distinction is important because foo can be reassigned to a non-local object. Alternately, simply omitting 'new' entirely might be feasible, though the meaning there is less obvious. As I said in #d: Foo Bar() { return new Foo(); } auto foo = Bar(); looks like a stack-based initialization even though it's not. But perhaps it doesn't matter in this case, as nothing will break if a heap-based instance is used in place of a stack-based instance, it's replacing things the other direction that can cause problems. Sean
Feb 20 2006
parent Sean Kelly <sean f4.ca> writes:
Charles wrote:
 auto foo = local Bar();
This gets my vote , but why is everyone using 'auto' ( deduction )keyword here, gets a little confusing since you're trying to replace the other auto with local. ( For people not in on the #d discussion ).
Just to make things extra confusing :-)
 MyClass foo = local MyClass("parameters");
 
 yes ?
 
 So 'local' replaces 'new' for stack based allocations.
Yes. Sean
Feb 20 2006
prev sibling next sibling parent reply Mike Capp <mike.capp gmail.com> writes:
In article <dtdb2e$2lsp$1 digitaldaemon.com>, Sean Kelly says...
If we're moving towards stack-based auto classes then I'd prefer the 
distinction be associated with the object and not the reference.  ie.

auto foo = local Bar();

I think the distinction is important because foo can be reassigned to a 
non-local object.
Not currently, it can't. From http://www.digitalmars.com/d/attribute.html#auto : "Assignment to an auto, other than initialization, is not allowed." cheers, Mike
Feb 20 2006
parent reply Georg Wrede <georg.wrede nospam.org> writes:
Mike Capp wrote:
 In article <dtdb2e$2lsp$1 digitaldaemon.com>, Sean Kelly says...
 
 If we're moving towards stack-based auto classes then I'd prefer
 the distinction be associated with the object and not the
 reference.  ie.
 
 auto foo = local Bar();
 
 I think the distinction is important because foo can be reassigned
 to a non-local object.
Not currently, it can't. From http://www.digitalmars.com/d/attribute.html#auto : "Assignment to an auto, other than initialization, is not allowed."
If 'local' were implemented, then it could, since then the meaning of 'auto' would only mean auto-typing and not RAII.
Feb 20 2006
parent reply Georg Wrede <georg.wrede nospam.org> writes:
Georg Wrede wrote:
 Mike Capp wrote:
 
 In article <dtdb2e$2lsp$1 digitaldaemon.com>, Sean Kelly says...

 If we're moving towards stack-based auto classes then I'd prefer
 the distinction be associated with the object and not the
 reference.  ie.

 auto foo = local Bar();

 I think the distinction is important because foo can be reassigned
 to a non-local object.
Not currently, it can't. From http://www.digitalmars.com/d/attribute.html#auto : "Assignment to an auto, other than initialization, is not allowed."
If 'local' were implemented, then it could, since then the meaning of 'auto' would only mean auto-typing and not RAII.
On second thought, local Bla bla = new Bla(); // RR, heap storage auto bla = new Bla(); // autotyped, heap storage Bla bla = new Bla(); // heap storage local Bla bla = local Bla(); // RR, stack storage auto bla = local Bla(); // autotyped, stack storage, no RR Bla bla = local Bla(); // stack storage, no RR This brings up a few problems. First, the word 'local' is just about as smart as 'auto', i.e. it is misleading and ambiguous for what we're using it for. Second, do we really need this fine of a control over both storage and disposal? For the compiler writer, at first sight, keeping track of RR (RAII) here might look like a lot of work. But it actually is ok: "the variable knows" whether to invoke RR, so RR will be invoked irrespective of who happens to be referenced by it. This may actually open up new ways of using RR? One potential, hard problem is, this decouples RR-ness from the object instance, making it a property of the reference (the variable). This is obviously not in the spirit of why we have RR in the first place. ---- Unless we can sort out what we want here, I think the current state of RR is adequate -- _except_ that I want another word substituted for 'auto'! We can't have it mean "autotype and/or RAII", at the same time. That is just too much of a disgrace.
Feb 21 2006
parent reply Georg Wrede <georg.wrede nospam.org> writes:
Georg Wrede wrote:
 Georg Wrede wrote:
 Mike Capp wrote:
 Sean Kelly says...
 
 If we're moving towards stack-based auto classes then I'd
 prefer the distinction be associated with the object and not
 the reference.  ie.
 
 auto foo = local Bar();
 
 I think the distinction is important because foo can be
 reassigned to a non-local object.
Not currently, it can't. From http://www.digitalmars.com/d/attribute.html#auto : "Assignment to an auto, other than initialization, is not allowed."
Currently (D.144) it _is_ allowed. (Obviously a bug.)
 If 'local' were implemented, then it could, since then the meaning
 of 'auto' would only mean auto-typing and not RAII.
On second thought, local Bla bla = new Bla(); // RR, heap storage auto bla = new Bla(); // autotyped, heap storage Bla bla = new Bla(); // heap storage local Bla bla = local Bla(); // RR, stack storage auto bla = local Bla(); // autotyped, stack storage, no RR Bla bla = local Bla(); // stack storage, no RR
Reordering the lines above might make it clearer: local Bla bla = new Bla(); // RR, heap storage local Bla bla = local Bla(); // RR, stack storage auto bla = new Bla(); // autotyped, heap storage auto bla = local Bla(); // autotyped, stack storage, no RR Bla bla = new Bla(); // heap storage Bla bla = local Bla(); // stack storage, no RR and consequently also: local auto bla = new Bla(); // RR, autotyped, heap storage local auto bla = local Bla(); // RR, autotyped, stack storage
 This brings up a few problems. First, the word 'local' is just about
 as smart as 'auto', i.e. it is misleading and ambiguous for what
 we're using it for.
 
 Second, do we really need this fine of a control over both storage
 and disposal?
 
 For the compiler writer, at first sight, keeping track of RR (RAII)
 here might look like a lot of work. But it actually is ok: "the
 variable knows" whether to invoke RR, so RR will be invoked
 irrespective of who happens to be referenced by it.
 
 This may actually open up new ways of using RR?
Sigh, shouldn't try to think before noon:
 One potential, hard problem is, this decouples RR-ness from the
 object instance, making it a property of the reference (the
 variable). This is obviously not in the spirit of why we have RR in
 the first place.
Ok, RR-ness can be coupled with - the reference - the assignment - the instance - the class Of these, I'd see that instance and class should be made equivalent, since it would be clearer to have separate classes (one requiring RR and the other not) for purposes where _sometimes_ the instance absolutely needs to be RR only. (As opposed to storing knowledge of such a need in an instance variable.) Currently (D.144) couples RR-ness with the reference. Which is sort of ok, *except* for the fact that one now can assign (e.g.) a global instance to the reference, thus (probably inadvertently) marking it for impending destruction. One can also assign an instance created as RR to (e.g.) a global variable, and then get surprised at the later occurring access violation because the instance got destroyed, even if other references to it exist. Coupling RR-ness with the assignment is an intriguing alternative. This has the possibility of creating really robust code. Then the compiler could prevent other assignments to the reference, and it could prevent assignment of the instance to any variable with a longer scope than the original reference.
 ----
 
 Unless we can sort out what we want here, I think the current state
 of RR is adequate -- _except_ that I want another word substituted
 for 'auto'! We can't have it mean "autotype and/or RAII", at the same
 time. That is just too much of a disgrace.
To summarize: It would be handy to have a class that _requires_ RR instantiation. It would also be handy if RR is with the assignment. (That is, forcefully welding the reference and the instance together.)
Feb 21 2006
parent reply Mike Capp <mike.capp gmail.com> writes:
In article <43FAF3AC.2080609 nospam.org>, Georg Wrede says...
 I want another word substituted
 for 'auto'! We can't have it mean "autotype and/or RAII", at the same
 time. That is just too much of a disgrace.
Amen.
To summarize:

It would be handy to have a class that _requires_ RR instantiation.
And it's not that big a leap. Currently I believe you can declare a class "auto" to force all instances to be auto; you'd just have to beef up this rule to say that ONLY instances of auto classes can be declared auto. This is probably going to get me chased out of town with torches and pitchforks, but I'd actually like to go one step further and rule that ONLY auto classes can define destructors. The thinking being that if you care enough about a managed resource to write a destructor to release it, you almost certainly want that destructor called deterministically. Relying on the garbage collector to call it for you in a timely fashion is almost certainly setting you up for a nasty surprise. Far too many people still seem to think that GC is a panacea for resource management generally, not just memory management, and until they're jolted out of that I don't have much hope for D's RAII support improving. (Incidentally, what's with this "RR"??? I've never seen it before in 10 years of writing C++. If you mean RAII, it's probably less confusing to the reader to say RAII, however silly an acronym it might be.) cheers, Mike
Feb 21 2006
next sibling parent Georg Wrede <georg.wrede nospam.org> writes:
Mike Capp wrote:
 Georg Wrede says...
 
 I want another word substituted for 'auto'! We can't have it mean
 "autotype and/or RAII", at the same time. That is just too much
 of a disgrace.
Amen.
 To summarize:
 
 It would be handy to have a class that _requires_ RR instantiation.
And it's not that big a leap. Currently I believe you can declare a class "auto" to force all instances to be auto; you'd just have to beef up this rule to say that ONLY instances of auto classes can be declared auto.
How about file descriptors and the like? I think there's a lot of stuff that will sometimes be "auto" and sometimes not. It all depends on the local needs in code. Opening a socket in a function call, and passing its reference around while communicating, is an example of where auto would be cumbersome. Then again, another program that opens many sockets for a short while each, might really benefit from a guaranteed short lived socket.
 This is probably going to get me chased out of town with torches and
 pitchforks, but I'd actually like to go one step further and rule
 that ONLY auto classes can define destructors. 
Hmm. This I find a lot more attractive.
 The thinking being
 that if you care enough about a managed resource to write a
 destructor to release it, you almost certainly want that destructor
 called deterministically. Relying on the garbage collector to call it
  for you in a timely fashion is almost certainly setting you up for a
 nasty surprise. Far too many people still seem to think that GC is a
 panacea for resource management generally, not just memory
 management, and until they're jolted out of that I don't have much
 hope for D's RAII support improving.
Maybe we should solicit for counter examples? If none are found, then we probably should implement this.
 (Incidentally, what's with this "RR"??? I've never seen it before in
 10 years of writing C++. If you mean RAII, it's probably less
 confusing to the reader to say RAII, however silly an acronym it
 might be.)
Depends on the reader. ;-) Check out digitalmars.D:32289.
Feb 21 2006
prev sibling parent reply Don Clugston <dac nospam.com.au> writes:
Mike Capp wrote:
 In article <43FAF3AC.2080609 nospam.org>, Georg Wrede says...
 I want another word substituted
 for 'auto'! We can't have it mean "autotype and/or RAII", at the same
 time. That is just too much of a disgrace.
Amen.
 To summarize:

 It would be handy to have a class that _requires_ RR instantiation.
And it's not that big a leap. Currently I believe you can declare a class "auto" to force all instances to be auto; you'd just have to beef up this rule to say that ONLY instances of auto classes can be declared auto. This is probably going to get me chased out of town with torches and pitchforks, but I'd actually like to go one step further and rule that ONLY auto classes can define destructors. The thinking being that if you care enough about a managed resource to write a destructor to release it, you almost certainly want that destructor called deterministically.
You're saying, abolish finalisers from the language. Radical. But I agree. I have NEVER seen a single good use for a finaliser. I've only ever seen them used as "poor man's destructors". But I'll change my mind if anyone can show a use for them. Any takers? I bet removing finalisers would simplify the gc. However, there's still the issue of manual memory management. It would I think be possible to allow RAII classes to be created on the heap with new, and have the destructor called manually with delete. Whenever the gc runs, if it finds that it is able to collect an object which has a destructor, instead of calling it as a finaliser, it should assert -- a memory leak bug has been found. Alternatively, you could just use the C++ method and and perform the check only at the end of the program. (But it would be cool to have a function checkForMemoryLeaks() which could be run at any time, for anyone who still wants to use manual memory management. By using mark-and-sweep, you can detect a memory leak much earlier than in C/C++). Of course, if RAII classes on the heap are forbidden, it's easy -- the GC then never has to worry about destructors or finalisers, it can just release memory. Relying on the garbage collector to call it
 for you in a timely fashion is almost certainly setting you up for a nasty
 surprise. Far too many people still seem to think that GC is a panacea for
 resource management generally, not just memory management, and until they're
 jolted out of that I don't have much hope for D's RAII support improving.
Agreed. > (Incidentally, what's with this "RR"??? I've never seen it before in 10 years of
 writing C++. If you mean RAII, it's probably less confusing to the reader to
say
 RAII, however silly an acronym it might be.)
You could think of RAII as "Release At Imminent Incineration" <g> Or come up with a better interpretation of the letters.
 
 cheers,
 Mike
 
 
Feb 21 2006
parent Mike Capp <mike.capp gmail.com> writes:
In article <dtf7gr$1sla$1 digitaldaemon.com>, Don Clugston says...
You're saying, abolish finalisers from the language. Radical.
But I agree. I have NEVER seen a single good use for a finaliser.
Woohoo! I'd almost given up. (I have, several times, heard Java or .Net people enthuse about being able to 'resurrect' objects in their finalizers, but needless to say they never seem to supply a reason why you'd want to do something so braindead. One can only stare pityingly.)
I bet removing finalisers would simplify the gc.
Yes... I was going to mention that, but I wasn't 100% sure and it's kind of tangential to my main motivation, which is to slap people around the face with a large halibut until they realize that GC is not the Second Coming for resource management.
However, there's still the issue of manual memory management. It would I 
think be possible to allow RAII classes to be created on the heap with 
new, and have the destructor called manually with delete.
I'm not convinced that it's worth supporting. As soon as you get into manual destructor calls, you're separating the call from the object's lifetime, at which point I don't consider it a destructor in any useful sense. It's just a function that happens to do resource release, and I think that framing it in those terms would help prevent sloppy thinking. ("But it's a destructor, it can't possibly be called twice!")
Of course, if RAII classes on the heap are forbidden, it's easy -- the 
GC then never has to worry about destructors or finalisers, it can just 
release memory.
That would be my preference in many ways - it's always easier to relax a restriction later than to impose a new one - but if a RAII ref is being assigned from the result of a function call, you don't know the actual type at compile time, which would make stack allocation tricky. cheers, Mike
Feb 21 2006
prev sibling next sibling parent Georg Wrede <georg.wrede nospam.org> writes:
Sean Kelly wrote:
 Fredrik Olsson wrote:
 
 After some discussion on #d I though why not put my thoughts into more 
 permanent writing.

 Keyword auto is used for two reasons; implicit type and making sure 
 the object is destroyed when going out of scope. I suggest a new 
 keyword for the latter: local.

 local auto foo = new Bar();
If we're moving towards stack-based auto classes then I'd prefer the distinction be associated with the object and not the reference. ie. auto foo = local Bar(); I think the distinction is important because foo can be reassigned to a non-local object.
Bull's eye! Funny that nobody thought of this before.
 Alternately, simply omitting 'new' entirely might be 
 feasible, though the meaning there is less obvious.  As I said in #d:
 
 Foo Bar() { return new Foo(); }
 
 auto foo = Bar();
 
 looks like a stack-based initialization even though it's not.  But 
 perhaps it doesn't matter in this case, as nothing will break if a 
 heap-based instance is used in place of a stack-based instance, it's 
 replacing things the other direction that can cause problems.
In general, it's much harder to spot something is missing than to spot the wrong thing. So, I definitely vote for the keyword 'local' for stack storage. Besides, that's what it means in other languages, too. Much cleaner: new allocates on heap, local on stack.
Feb 20 2006
prev sibling parent reply Fredrik Olsson <peylow gmail.com> writes:
Sean Kelly skrev:
 Fredrik Olsson wrote:
 
 After some discussion on #d I though why not put my thoughts into more 
 permanent writing.

 Keyword auto is used for two reasons; implicit type and making sure 
 the object is destroyed when going out of scope. I suggest a new 
 keyword for the latter: local.

 local auto foo = new Bar();
If we're moving towards stack-based auto classes then I'd prefer the distinction be associated with the object and not the reference. ie. auto foo = local Bar();
I see your point, especially with the object later being replaced. Maybe I am trying to shoot to far By arguing for not focusing on "stack-based" but rather on "destroyed when exiting scope".
 I think the distinction is important because foo can be reassigned to a 
 non-local object.  Alternately, simply omitting 'new' entirely might be 
 feasible, though the meaning there is less obvious.  As I said in #d:
 
 Foo Bar() { return new Foo(); }
 
 auto foo = Bar();
 
 looks like a stack-based initialization even though it's not.  But 
 perhaps it doesn't matter in this case, as nothing will break if a 
 heap-based instance is used in place of a stack-based instance, it's 
 replacing things the other direction that can cause problems.
 
But still I find it could be usefully, especially in a case like this when using a function as a to create the objects. But to solve this I think the distinction should be associated with the assignment, not the variable, nor the object. Foo Bar() { return new Foo(); } auto foo = local Bar(); auto baz = local new Baz(); My point still being; that we should not be so focused on how the technical bits like how and where the object is allocated (on stack or heap), but how it should be handled (local to scope or not). If the spec does not specify how things should be done, then the implementation is more free to choose what is best for every case, even if the cases may vary as even more new features are added later on (Hopefully without more syntax revisions). regards // Fredrik
Feb 20 2006
next sibling parent Brad Roberts <braddr puremagic.com> writes:
On Tue, 21 Feb 2006, Fredrik Olsson wrote:

 My point still being; that we should not be so focused on how the 
 technical bits like how and where the object is allocated (on stack or 
 heap), but how it should be handled (local to scope or not). If the spec 
 does not specify how things should be done, then the implementation is 
 more free to choose what is best for every case, even if the cases may 
 vary as even more new features are added later on (Hopefully without 
 more syntax revisions).
 
 regards
 // Fredrik
I want to focus on the point. I have to strongly disagree, this sort of thing is what affects ABI's. If there's a desire to support more than one D compiler, this sort of thing can't be left ambiguous as it would make cross compiler compatibility a nightmare. A .o/.a/.so generated via dmd would have to successfully link with objects/archives/shared libraries created via other compilers. That means they'd have to behave the same with respect to anything that leaks out of a compilation unit. Aspects of this discussion might stay local enough to remain unspecified, if semantics leak outside of a single function, then it needs to be well defined. Later, Brad
Feb 20 2006
prev sibling parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Fredrik Olsson wrote:
 Sean Kelly skrev:
 
 Fredrik Olsson wrote:

 After some discussion on #d I though why not put my thoughts into 
 more permanent writing.

 Keyword auto is used for two reasons; implicit type and making sure 
 the object is destroyed when going out of scope. I suggest a new 
 keyword for the latter: local.

 local auto foo = new Bar();
If we're moving towards stack-based auto classes then I'd prefer the distinction be associated with the object and not the reference. ie. auto foo = local Bar();
I see your point, especially with the object later being replaced. Maybe I am trying to shoot to far By arguing for not focusing on "stack-based" but rather on "destroyed when exiting scope".
 I think the distinction is important because foo can be reassigned to 
 a non-local object.  Alternately, simply omitting 'new' entirely might 
 be feasible, though the meaning there is less obvious.  As I said in #d:

 Foo Bar() { return new Foo(); }

 auto foo = Bar();

 looks like a stack-based initialization even though it's not.  But 
 perhaps it doesn't matter in this case, as nothing will break if a 
 heap-based instance is used in place of a stack-based instance, it's 
 replacing things the other direction that can cause problems.
But still I find it could be usefully, especially in a case like this when using a function as a to create the objects. But to solve this I think the distinction should be associated with the assignment, not the variable, nor the object. Foo Bar() { return new Foo(); } auto foo = local Bar(); auto baz = local new Baz(); My point still being; that we should not be so focused on how the technical bits like how and where the object is allocated (on stack or heap), but how it should be handled (local to scope or not).
I think I agree (although not 100% certain yet) Think it would be cool if local men't destruct at end of scope no mater is the actual instance created in this function or not. Stack objects could still be created something like: auto foo = Foo(); or maybe auto baz = stack Foo(); or something else I somehow feel these features might complicate the language a lot.
Feb 21 2006
parent reply Fredrik Olsson <peylow gmail.com> writes:
Ivan Senji skrev:
 I think I agree (although not 100% certain yet)
 Think it would be cool if local men't destruct at end of scope no mater 
 is the actual instance created in this function or not.
 
 Stack objects could still be created something like:
 auto foo = Foo(); or maybe
 auto baz = stack Foo(); or something else
 
 I somehow feel these features might complicate the language a lot.
I better write a summary :), with this my first proposal we really just have four cases: // Object allways on heap, created from class, gc destroys whenever, // Object can be passed out of scope Foo foo = new Foo(); // Object allways on heap, created from another function, // gc destroys whenever, object can be passed out of scope Foo foo = Bar(); // Object could be on stack, created from class, scope exit destroys // imidiately, can not be passed out of scope Foo foo = local new Foo(); // Object allways on heap, created from another function, scope exit // destroys imidiately, can not be passed out of scope. Foo foo = local Bar(); And then auto could be used instead of Foo to declare the type, but that is beyond this discussion, and implied by auto _only_ meaning implicit type and nothing else. Since objects that are potentially on the stack can not pass out of scope, and if sent as argument to other function they are just pointers anyway, there should be no requirements for changing any ABI. Only addition is that local object on heap must be destroyed in the process of unwinding an exception. So any scope that uses local objects on heap must have an implicit try {} finally {} for releasing objects. // Fredrik Olsson
Feb 21 2006
next sibling parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
++votes;


-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O 
!M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y
------END GEEK CODE BLOCK------

Tomasz Stachowiak  /+ a.k.a. h3r3tic +/
Feb 21 2006
prev sibling parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Fredrik Olsson wrote:
 Ivan Senji skrev:
 
 I think I agree (although not 100% certain yet)
 Think it would be cool if local men't destruct at end of scope no 
 mater is the actual instance created in this function or not.

 Stack objects could still be created something like:
 auto foo = Foo(); or maybe
 auto baz = stack Foo(); or something else

 I somehow feel these features might complicate the language a lot.
I better write a summary :), with this my first proposal we really just have four cases: // Object allways on heap, created from class, gc destroys whenever, // Object can be passed out of scope Foo foo = new Foo(); // Object allways on heap, created from another function, // gc destroys whenever, object can be passed out of scope Foo foo = Bar(); // Object could be on stack, created from class, scope exit destroys
Everything sounds cool, but that *could* part troubles me :) It should either mean stack, or heap, or have a choise over that.
 // imidiately, can not be passed out of scope
 Foo foo = local new Foo();
 
 // Object allways on heap, created from another function, scope exit
 // destroys imidiately, can not be passed out of scope.
 Foo foo = local Bar();
 
 And then auto could be used instead of Foo to declare the type, but that 
 is beyond this discussion, and implied by auto _only_ meaning implicit 
 type and nothing else.
 
 Since objects that are potentially on the stack can not pass out of 
 scope, and if sent as argument to other function they are just pointers 
 anyway, there should be no requirements for changing any ABI.
 
 Only addition is that local object on heap must be destroyed in the 
 process of unwinding an exception. So any scope that uses local objects 
 on heap must have an implicit try {} finally {} for releasing objects.
 
 // Fredrik Olsson
Feb 21 2006
parent Fredrik Olsson <peylow gmail.com> writes:
Ivan Senji skrev:
 Fredrik Olsson wrote:
 
 Ivan Senji skrev:
 <snip>
 // Object could be on stack, created from class, scope exit destroys
Everything sounds cool, but that *could* part troubles me :) It should either mean stack, or heap, or have a choise over that.
'Could' always sounds scary, but then again we can not decide if the compiler should inline functions, they *could* all be inlined if the compiler so chooses. The point here is that this case is the most likely for the compiler to be able to do fancy stuff too, so why restrict it? I am sure that 9 of 10 implementations of D would use the stack. But what if another implementation for some reason or another do not want to go over the trouble to implement stack allocation? Or maybe even finds an even better way to do it, whatever that might be. The important point here is (if I have not completely misunderstood the intentions) to have an object that is destroyed when out of scope with as little overhead as possible. Using the stack for that purpose is good, but forcing, why? // Fredrik
Feb 21 2006
prev sibling next sibling parent S. Chancellor <dnewsgr mephit.kicks-ass.org> writes:
While I agree with your sentiment.  However, I think local associated 
with the reference is confusing as it leads people to believe it is 
somehow different from "global." (See Python's usage of these keywords) 
This would make much more sense associated with the object, like Sean 
kelly mentioned.  However, there is still problems with that.

While we're coming to a consensus on these things, let us fix the reuse 
of static, and the !is keyword as well.

-S.


On 2006-02-20 12:23:26 -0800, Fredrik Olsson <peylow gmail.com> said:

 After some discussion on #d I though why not put my thoughts into more 
 permanent writing.
 
 Keyword auto is used for two reasons; implicit type and making sure the 
 object is destroyed when going out of scope. I suggest a new keyword 
 for the latter: local.
 
 local auto foo = new Bar();
 
 Why? First of auto is only used for the implicit type, so no confusion. 
   The keyword local in itself describes pretty to the point what is 
 supposed to happen with the variable. And nothing is said about the 
 stack, so we are future proof if in the future we would like to also 
 have:
 
 local auto foo = Bar();
 
 Where Bar(); is a function returning an Object, but we still want the 
 object to be destructed when going out of this scope. The 
 implementation is quite different as the Object would need to be on 
 heap, but the syntax is the same. So local would indicate what should 
 be done (destroy when out of scope), not how it should be done 
 (allocate on stack or whatever).
 
 Even this could be possible, without syntax changes:
 {
    local Foo bar;
    // some code
    Baz(bar); // Jupp Baz have a inout parameter returning an object.
 } // And bar is still destroyed if set to something here...
 
 
 regards
 // Fredrik Olsson
Feb 20 2006
prev sibling next sibling parent James <James_member pathlink.com> writes:
Re auto for implicit typing. 

different keyword.
From Language Spec at http://msdn.microsoft.com/vcsharp/future/default.aspx 

Implicitly typed local variables 

In an implicitly typed local variable declaration, the type of the local
variable being declared is inferred from the expression used to initialize the
variable. When a local variable declaration specifies var as the type and no
type named var is in scope, the declaration is an implicitly typed local
variable declaration. For example:

var i = 5; 
var s = "Hello"; 
var d = 1.0; 
var numbers = new int[] {1, 2, 3}; 
var orders = new Dictionary<int,Order>();

The implicitly typed local variable declarations above are precisely equivalent
to the following explicitly typed declarations:

int i = 5; 
string s = "Hello"; 
double d = 1.0; 
int[] numbers = new int[] {1, 2, 3}; 
Dictionary<int,Order> orders = new Dictionary<int,Order>();

A local variable declarator in an implicitly typed local variable declaration is
subject to the following restrictions:

The declarator must include an initializer. 
The initializer must be an expression. The initializer cannot be an object or
collection initializer (§26.4) by itself, but it can be a new expression that
includes an object or collection initializer. 
The compile-time type of the initializer expression cannot be the null type. 
If the local variable declaration includes multiple declarators, the
initializers must all have the same compile-time type. 
The following are examples of incorrect implicitly typed local variable
declarations:

var x;     // Error, no initializer to infer type from 
var y = {1, 2, 3}; // Error, collection initializer not permitted 
var z = null;   // Error, null type not permitted

~~~~~~~~~~~

gcc and make it a compiled language. With the additional of auto for stack based
deterministic finalisation for objects.  
Feb 21 2006
prev sibling next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 20 Feb 2006 21:23:26 +0100, Fredrik Olsson <peylow gmail.com>  
wrote:
 After some discussion on #d I though why not put my thoughts into more  
 permanent writing.

 Keyword auto is used for two reasons; implicit type and making sure the  
 object is destroyed when going out of scope. I suggest a new keyword for  
 the latter: local.

 local auto foo = new Bar();

 Why? First of auto is only used for the implicit type, so no confusion.  
   The keyword local in itself describes pretty to the point what is  
 supposed to happen with the variable. And nothing is said about the  
 stack, so we are future proof if in the future we would like to also  
 have:

 local auto foo = Bar();

 Where Bar(); is a function returning an Object, but we still want the  
 object to be destructed when going out of this scope. The implementation  
 is quite different as the Object would need to be on heap, but the  
 syntax is the same. So local would indicate what should be done (destroy  
 when out of scope), not how it should be done (allocate on stack or  
 whatever).

 Even this could be possible, without syntax changes:
 {
    local Foo bar;
    // some code
    Baz(bar); // Jupp Baz have a inout parameter returning an object.
 } // And bar is still destroyed if set to something here...
I thought the plan was to deprecate "auto" WRT declaring stack based auto destructed class instances, resulting in: class A {} A a = new A(); //heap alloc A a = A(); //stack alloc, destruct at scope exit So, "auto" would only mean "automatic type determination": auto a = new A(); //heap alloc, 'a' is of type reference to 'A' auto a = A(); //stack alloc, destruct at scope exit, 'a' is of type reference to 'A' Regan
Feb 21 2006
parent reply AgentOrange <AgentOrange_member pathlink.com> writes:
In article <ops5bhg5ol23k2f5 nrage.netwin.co.nz>, Regan Heath says...
On Mon, 20 Feb 2006 21:23:26 +0100, Fredrik Olsson <peylow gmail.com>  
wrote:
 After some discussion on #d I though why not put my thoughts into more  
 permanent writing.

 Keyword auto is used for two reasons; implicit type and making sure the  
 object is destroyed when going out of scope. I suggest a new keyword for  
 the latter: local.

 local auto foo = new Bar();

 Why? First of auto is only used for the implicit type, so no confusion.  
   The keyword local in itself describes pretty to the point what is  
 supposed to happen with the variable. And nothing is said about the  
 stack, so we are future proof if in the future we would like to also  
 have:

 local auto foo = Bar();

 Where Bar(); is a function returning an Object, but we still want the  
 object to be destructed when going out of this scope. The implementation  
 is quite different as the Object would need to be on heap, but the  
 syntax is the same. So local would indicate what should be done (destroy  
 when out of scope), not how it should be done (allocate on stack or  
 whatever).

 Even this could be possible, without syntax changes:
 {
    local Foo bar;
    // some code
    Baz(bar); // Jupp Baz have a inout parameter returning an object.
 } // And bar is still destroyed if set to something here...
I thought the plan was to deprecate "auto" WRT declaring stack based auto destructed class instances, resulting in: class A {} A a = new A(); //heap alloc A a = A(); //stack alloc, destruct at scope exit So, "auto" would only mean "automatic type determination": auto a = new A(); //heap alloc, 'a' is of type reference to 'A' auto a = A(); //stack alloc, destruct at scope exit, 'a' is of type reference to 'A' Regan
are we going to lose static opCall? yikes!
Feb 21 2006
parent reply Fredrik Olsson <peylow gmail.com> writes:
AgentOrange skrev:
 In article <ops5bhg5ol23k2f5 nrage.netwin.co.nz>, Regan Heath says...
 
On Mon, 20 Feb 2006 21:23:26 +0100, Fredrik Olsson <peylow gmail.com>  
 <snip>
auto a = new A(); //heap alloc, 'a' is of type reference to 'A'
auto a = A();     //stack alloc, destruct at scope exit, 'a' is of type  
reference to 'A'

Regan
are we going to lose static opCall? yikes!
And the possibility of allowing non stack objects to automatically go out of scope in the future without changing the syntax? I do not say that it should be added now, all I say is that it would be good if the syntax allowed for it. Ones we go 1.0 much of the syntax will pretty much have to stay, so better be prepared :). A functionality restricted by the compiler is easier to fix and causes less harm than a feature restricted by the syntax. Plus with: auto a = A(); It is absolutely no way to just at a glance make sure with 100% sertenty that a is not assigned the result of a function, instead of being instantiated on the stack. // Fredrik
Feb 21 2006
next sibling parent reply Don Clugston <dac nospam.com.au> writes:
Fredrik Olsson wrote:
 AgentOrange skrev:
 In article <ops5bhg5ol23k2f5 nrage.netwin.co.nz>, Regan Heath says...

 On Mon, 20 Feb 2006 21:23:26 +0100, Fredrik Olsson 
 <peylow gmail.com>  <snip>
 auto a = new A(); //heap alloc, 'a' is of type reference to 'A'
 auto a = A();     //stack alloc, destruct at scope exit, 'a' is of 
 type  reference to 'A'

 Regan
are we going to lose static opCall? yikes!
And the possibility of allowing non stack objects to automatically go out of scope in the future without changing the syntax? I do not say that it should be added now, all I say is that it would be good if the syntax allowed for it. Ones we go 1.0 much of the syntax will pretty much have to stay, so better be prepared :). A functionality restricted by the compiler is easier to fix and causes less harm than a feature restricted by the syntax. Plus with: auto a = A(); It is absolutely no way to just at a glance make sure with 100% sertenty that a is not assigned the result of a function, instead of being instantiated on the stack.
Does that matter? After all, a constructor is just a function. Clearly a new variable 'a' is being declared, it's type will be the return value of A(), and then A() needs to be called to initialise it. Or have I missed something?
Feb 22 2006
parent Fredrik Olsson <peylow treyst.se> writes:
Don Clugston skrev:
 Fredrik Olsson wrote:
 AgentOrange skrev:
 In article <ops5bhg5ol23k2f5 nrage.netwin.co.nz>, Regan Heath says...
<snip>
 Plus with: auto a = A();
 It is absolutely no way to just at a glance make sure with 100% 
 sertenty that a is not assigned the result of a function, instead of 
 being instantiated on the stack.
Does that matter? After all, a constructor is just a function. Clearly a new variable 'a' is being declared, it's type will be the return value of A(), and then A() needs to be called to initialise it. Or have I missed something?
Not really. I just like to be able to see with a glance what my code does. I think it is good for productivity, code maintenance, and in general make the programming language look nice. // Fredrik
Feb 22 2006
prev sibling parent Georg Wrede <georg.wrede nospam.org> writes:
Fredrik Olsson wrote:
 And the possibility of allowing non stack objects to automatically go
 out of scope in the future without changing the syntax? 
This is important. For the destruction itself, it makes no difference whether an object is on the stack or on the heap. A programmer might have an opinion on where to initially store the object, but that has to do with issues like heap fragmentation, or whatever else except destruction details.
 Ones we go 1.0 much of the syntax will
 pretty much have to stay, so better be prepared :). A functionality
 restricted by the compiler is easier to fix and causes less harm than
 a feature restricted by the syntax.
True!
 Plus with: auto a = A(); It is absolutely no way to just at a glance
 make sure with 100% sertenty that a is not assigned the result of a
 function, instead of being instantiated on the stack.
Yes. And even more important, it should be obvious and stand out to the human reader -- or else debugging becomes a pain. That is, if the programmer has an opinion on where the object should be, then that opinion should stand out. If he doesn't care, then that should be the simplest syntax. Likewise, and /separately/ from that, it should be equally obvious if the programmer wanted it to be a scoped object. But if he didn't, then it does _not_ have to stand out (i.e. use normal syntax here), since the default has always been to not force immediate destruction.
Feb 22 2006
prev sibling next sibling parent reply james <james_member pathlink.com> writes:
Could auto also be used in class definitions as well as stack finalisaton of
objects e.g

class X {

// the object is destroyed automatically when the class X is destroyed.
auto A a = new A();
}

I like the additonal control.  If i've declared an object and i know that the
object is definitely NOT referenced by any other variable i want the semantics
and syntax to reflect that. And any performance gains is useful.
So auto would be used for
- stack scoped objects - either the scope co
- object that are 'children' of the class they are declared and should be
destroyed when the parent is destroyed.

Personally i would like the above use of auto and make gc explicit ie:
gc A a = new A();


var a = new A();
Feb 21 2006
parent reply Georg Wrede <georg.wrede nospam.org> writes:
james wrote:
 Could auto also be used in class definitions as well as stack finalisaton of
 objects e.g
 
 class X {
 
 // the object is destroyed automatically when the class X is destroyed.
 auto A a = new A();
 }
(You mean _instance_ above, right? Classes don't get destroyed.)
 Personally i would like the above use of auto and make gc explicit ie:
 gc A a = new A();
GC has nothing to do with this. If a programmer wants an object destroyed immediately after going out of scope (by whatever mechanism it may eventually happen), then this applies to GC collected programs as well as non-GC-collected. (e.g. C++)
Feb 22 2006
parent james <james_member pathlink.com> writes:
In article <43FC743C.9090601 nospam.org>, Georg Wrede says...
james wrote:
 Could auto also be used in class definitions as well as stack finalisaton of
 objects e.g
 
 class X {
 
 // the object is destroyed automatically when the class X is destroyed.
 auto A a = new A();
 }
(You mean _instance_ above, right? Classes don't get destroyed.)
Correct.
 Personally i would like the above use of auto and make gc explicit ie:
 gc A a = new A();
GC has nothing to do with this. If a programmer wants an object destroyed immediately after going out of scope (by whatever mechanism it may eventually happen), then this applies to GC collected programs as well as non-GC-collected. (e.g. C++)
It seems that the debate on auto has to do with how much explicit control the programmer has over object creation/destruction and memory management. Programmers who like auto are probably less keen on gc. And maybe would prefer it as optional rather than by default. Though technically auto and gc are not related.
Feb 22 2006
prev sibling parent Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Fredrik Olsson wrote:
 After some discussion on #d I though why not put my thoughts into more 
 permanent writing.
 
 Keyword auto is used for two reasons; implicit type and making sure the 
 object is destroyed when going out of scope. I suggest a new keyword for 
 the latter: local.
 
Regardless of semantic changes (as a semantic change in auto-RAII might make it work without keyword), I wish for: auto for auto-RAII var for auto-type Why these names? Auto-RAII implies an action in run-time, whereas auto-type is a compile-time only action, with no run-time effects. The name 'auto' sounds more action-like than 'var', so it fits better being assigned to auto-RAII. Also, 'var' is shorter than 'auto', with only three letters, which is also nice, since auto-type is mainly a syntactic sugar feature, so with 'var' it is one less character to type. I wonder what Walter's plans for this are. It's been a while since this ambiguity was introduced and news on this have come. -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Feb 24 2006