www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - auto, var, raii,scope, banana

reply kris <foo bar.com> writes:
Don has a good point: changing to "var" would cause conflict with 
existing variable-names.

Chad et. al. also have a good point about the conflict regarding static 
opCall() (via the lack of a "new" keyword). I suspect many people find 
the use of "new" to be indicative of allocation, and breaking this 
consistency may have a detrimental effect? Further, it was noted that a 
missing "new" can only be used at the instantiation site -- not at the 
class decl -- thus, D would be losing an existing feature.

I suspect you could count the current number of raii-class uses on a few 
hands, whereas the use of "auto" for implied-type is pretty darned 
popular -- and rightly so, since it's really very, very useful. Changing 
the raii style to use a different keyword, whilst retaining implied-type 
"auto" would be an almost imperceptible change?

Thus, it would appear to make sense to retain "auto" for implied-type, 
and introduce something *else* for automatic cleanup at end-of-scope 
(and also as a class attribute). how about reusing the "scope" keyword?

void main()
{
   auto i = 10;
   auto foo = new Foo;
   auto scope bar = new Bar;
   auto scope wumpus = new Wumpus;
}

class Foo {}

class Bar {}

scope class Wumpus {}
Jul 25 2006
next sibling parent reply Nils Hensel <nils.hensel web.de> writes:
kris schrieb:
 Don has a good point: changing to "var" would cause conflict with 
 existing variable-names.

I'm sorry but I don't believe there are many programmers out there actually using something as undescriptive as "var" as a regular identifier. I also strongly believe that no one should. It's the implication of a maintenance nightmare. I don't intend to insult Don in any way but it's a horrible practice IMNSHO that should not be preserved. So let's not focus on some odd minority but rather on the wide use of "var" in the context of type inference and dynamic typing. Also I don't think that it's a good habit to be looking at how C++ does something unless one is looking for a bad example. My main reason for interest in D is because personally I'm fed up with C++ and consider it an abomination and a major PITA. Just my 0.02 EUROs, Nils
Jul 25 2006
next sibling parent kris <foo bar.com> writes:
Nils Hensel wrote:
 kris schrieb:
 
 Don has a good point: changing to "var" would cause conflict with 
 existing variable-names.

I'm sorry but I don't believe there are many programmers out there actually using something as undescriptive as "var" as a regular identifier. I also strongly believe that no one should. It's the implication of a maintenance nightmare. I don't intend to insult Don in any way but it's a horrible practice IMNSHO that should not be preserved. So let's not focus on some odd minority but rather on the wide use of "var" in the context of type inference and dynamic typing. Also I don't think that it's a good habit to be looking at how C++ does something unless one is looking for a bad example. My main reason for interest in D is because personally I'm fed up with C++ and consider it an abomination and a major PITA. Just my 0.02 EUROs, Nils

Well, it would have notable impact on existing code to change auto to var. They're at least equally clear in my view, so it would come down to a question of impact upon existing code. What's more important is the clarification of what "auto" means. Right now, it's somewhat confused (with raii). If we instead use "scope" to indicate raii, that confusion just goes away. Besides, "scope" is a fine attribute for things that are "scoped" :)
Jul 25 2006
prev sibling next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 25 Jul 2006 20:14:52 +0200, Nils Hensel <nils.hensel web.de> wrote:
 kris schrieb:
 Don has a good point: changing to "var" would cause conflict with  
 existing variable-names.

I'm sorry but I don't believe there are many programmers out there actually using something as undescriptive as "var" as a regular identifier. I also strongly believe that no one should. It's the implication of a maintenance nightmare. I don't intend to insult Don in any way but it's a horrible practice IMNSHO that should not be preserved.

I don't use "var" specifically but I have been known to use tmp, x, y, i, j, p, s, n, .. for all my temporary and/or meaningless variables. They typically have a short scope life and I can't see a problem with this practice.
 So let's not focus on some odd minority but rather on the wide use of  
 "var" in the context of type inference and dynamic typing.

I think Kris's point is that of the two choices 'var' and 'auto' the latter is less likely to annoy someone by colliding with existing user variables. The point is valid so long as the group of 'var' users is bigger than the group of 'auto' users, even if both groups are small.
 Also I don't think that it's a good habit to be looking at how C++ does  
 something unless one is looking for a bad example. My main reason for  
 interest in D is because personally I'm fed up with C++ and consider it  
 an abomination and a major PITA.

C++ may be an abomination but it does have 'market' dominance. You have to ask 'why'. You should learn from your 'enemies' ;) Regan
Jul 25 2006
parent reply Nils Hensel <nils.hensel web.de> writes:
Regan Heath schrieb:
 I don't use "var" specifically but I have been known to use tmp, x, y, 
 i, j, p, s, n, .. for all my temporary and/or meaningless variables. 
 They typically have a short scope life and I can't see a problem with 
 this practice.

it is a lot more descriptive than "var". Not all variables are holding temporary values but all are "variable" as their name already implies. Even i(=index) or n(=number of) bear a meaning in a mathematical context. I'm not all against short variable names (though I try to usually be more expressive) but their name should hint at their content or use. "var" doesn't hint at anything.
 I think Kris's point is that of the two choices 'var' and 'auto' the 
 latter is less likely to annoy someone by colliding with existing user 
 variables. The point is valid so long as the group of 'var' users is 
 bigger than the group of 'auto' users, even if both groups are small.

1.0 yet. Since no one else already uses "auto" for this purpose but a lot of languages use "var" I believe it to be the more intuitive option.
 C++ may be an abomination but it does have 'market' dominance. You have 
 to ask 'why'. You should learn from your 'enemies' ;)

the least of all evils". This does not even hold true anymore. At least not when you look at language constructs and elegance. It's clearly "grown" not designed. Regards, Nils
Jul 25 2006
next sibling parent Don Clugston <dac nospam.com.au> writes:
Nils Hensel wrote:
 Regan Heath schrieb:
 I don't use "var" specifically but I have been known to use tmp, x, y, 
 i, j, p, s, n, .. for all my temporary and/or meaningless variables. 
 They typically have a short scope life and I can't see a problem with 
 this practice.

it is a lot more descriptive than "var". Not all variables are holding temporary values but all are "variable" as their name already implies. Even i(=index) or n(=number of) bear a meaning in a mathematical context. I'm not all against short variable names (though I try to usually be more expressive) but their name should hint at their content or use. "var" doesn't hint at anything.

It does. When I use it, 'var' is not an abbreviation of 'variable', it's an abbreviation of 'variant'.
 I think Kris's point is that of the two choices 'var' and 'auto' the 
 latter is less likely to annoy someone by colliding with existing user 
 variables. The point is valid so long as the group of 'var' users is 
 bigger than the group of 'auto' users, even if both groups are small.

1.0 yet. Since no one else already uses "auto" for this purpose but a lot of languages use "var" I believe it to be the more intuitive option.
 C++ may be an abomination but it does have 'market' dominance. You 
 have to ask 'why'. You should learn from your 'enemies' ;)

the least of all evils". This does not even hold true anymore. At least not when you look at language constructs and elegance. It's clearly "grown" not designed. Regards, Nils

Jul 26 2006
prev sibling parent "Andrei Khropov" <andkhropov nospam_mtu-net.ru> writes:
Nils Hensel wrote:

 I think Kris's point is that of the two choices 'var' and 'auto' the
 latter is less likely to annoy someone by colliding with existing user
 variables. The point is valid so long as the group of 'var' users is
 bigger than the group of 'auto' users, even if both groups are small.

yet. Since no one else already uses "auto" for this purpose but a lot of languages use "var" I believe it to be the more intuitive option.

Agreed ( it's also one letter shorter :-) ) -- AKhropov
Jul 27 2006
prev sibling parent reply Don Clugston <dac nospam.com.au> writes:
Nils Hensel wrote:
 kris schrieb:
 Don has a good point: changing to "var" would cause conflict with 
 existing variable-names.

I'm sorry but I don't believe there are many programmers out there actually using something as undescriptive as "var" as a regular identifier.

Maybe my first impression of the google search yourself -- the data is there. I also strongly believe that no one should. It's the
 implication of a maintenance nightmare.

 I don't intend to insult Don in any way but it's a horrible practice 
 IMNSHO that should not be preserved.

I don't understand. I can't see the difference between 'var' and 'x'. Do you also dislike use of 'i' as a counter variable in a for loop? (And if not, what is the difference?)
 So let's not focus on some odd minority but rather on the wide use of 
 "var" in the context of type inference and dynamic typing.

'var' is inappropriate in a statically typed language. Remember that 'static's are variables too. Note that 'auto' was one of the original C keywords, and was chosen without any constraint (no legacy code whatsoever, they could have chosen any name, including 'var'). Every variable was classed into either: static auto register
 Also I don't think that it's a good habit to be looking at how C++ does 
 something unless one is looking for a bad example. My main reason for 
 interest in D is because personally I'm fed up with C++ and consider it 
 an abomination and a major PITA.

Agreed, but the 'auto' thing ultimately comes from C, not C++.
Jul 25 2006
parent reply Nils Hensel <nils.hensel web.de> writes:
Don Clugston schrieb:
 Nils Hensel wrote:
 I'm sorry but I don't believe there are many programmers out there 
 actually using something as undescriptive as "var" as a regular 
 identifier. 

Maybe my first impression of the google search yourself -- the data is there.

I was thinking of professionals used to the idiosyncrasies of medium to large software projects, where you're often faced with working on and maintaining someone elses code. I guess if the best description of a variable's intended meaning this somebody could come up with was "var" I'd be pretty pissed pretty soon.
 I don't intend to insult Don in any way but it's a horrible practice 
 IMNSHO that should not be preserved.

I don't understand. I can't see the difference between 'var' and 'x'. Do you also dislike use of 'i' as a counter variable in a for loop? (And if not, what is the difference?)

already bear a meaning even if they look indescriptive. OTOH if someone uses 'i' as a string or a boolean variable I WOULD consider it a bad practice as well.
 'var' is inappropriate in a statically typed language. Remember that 
 'static's are variables too. Note that 'auto' was one of the original C 
 keywords, and was chosen without any constraint (no legacy code 
 whatsoever, they could have chosen any name, including 'var'). Every 
 variable was classed into either:
 
 static
 auto
 register

are storage classes in these contexts (as they are originally in D). C has no concept of type inference. "auto" just means that the memory management for these variables is dealt with automatically because these variables exist on the stack. D just uses the fact that "auto" signifies the declaration of a variable which allows the compiler to identify the type automatically through the initializing value. The same holds true for "static" and "const". So actually D doesn't have an explicit type inference keyword yet.
 Also I don't think that it's a good habit to be looking at how C++ 
 does something unless one is looking for a bad example. My main reason 
 for interest in D is because personally I'm fed up with C++ and 
 consider it an abomination and a major PITA.

Agreed, but the 'auto' thing ultimately comes from C, not C++.

totally different from it's current D counterpart. Regards, Nils
Jul 27 2006
parent reply Don Clugston <dac nospam.com.au> writes:
Nils Hensel wrote:
 Don Clugston schrieb:
 Nils Hensel wrote:
 I'm sorry but I don't believe there are many programmers out there 
 actually using something as undescriptive as "var" as a regular 
 identifier. 

Maybe my first impression of the google search yourself -- the data is there.

I was thinking of professionals used to the idiosyncrasies of medium to large software projects, where you're often faced with working on and maintaining someone elses code. I guess if the best description of a variable's intended meaning this somebody could come up with was "var" I'd be pretty pissed pretty soon.

They're normally in trivial one-line functions.
 I don't intend to insult Don in any way but it's a horrible practice 
 IMNSHO that should not be preserved.

I don't understand. I can't see the difference between 'var' and 'x'. Do you also dislike use of 'i' as a counter variable in a for loop? (And if not, what is the difference?)

already bear a meaning even if they look indescriptive. OTOH if someone uses 'i' as a string or a boolean variable I WOULD consider it a bad practice as well.

 'var' is inappropriate in a statically typed language. Remember that 
 'static's are variables too. Note that 'auto' was one of the original 
 C keywords, and was chosen without any constraint (no legacy code 
 whatsoever, they could have chosen any name, including 'var'). Every 
 variable was classed into either:

 static
 auto
 register

are storage classes in these contexts (as they are originally in D). C has no concept of type inference. "auto" just means that the memory management for these variables is dealt with automatically because these variables exist on the stack.

 D just uses the fact that "auto" signifies the declaration of a variable 
  which allows the compiler to identify the type automatically  through 
 the initializing value. The same holds true for "static" and "const". So 
 actually D doesn't have an explicit type inference keyword yet.

No, the idea is *not* to have a type inference keyword, but instead only specify the storage class: static a = 7; const b = 7; auto c = 7; Now 'a' is a variable, just as much 'c' is. Are you proposing that you'd have to type: static var x = func(7); ? Surely not. 'const var' would be an abomination! The problem is, there's no storage class for local variables. In C/C++, there is, and it's called 'auto', but it's extremely rarely used in normal code. 'local' is perhaps the most natural name. I just don't like the idea that 'var' would mean "local non-static variable". "Variable" is a much broader category than "local variable". I hope that one day D also gets explicit thread-local variables. They would need a seperate storage class.
 Also I don't think that it's a good habit to be looking at how C++ 
 does something unless one is looking for a bad example. My main 
 reason for interest in D is because personally I'm fed up with C++ 
 and consider it an abomination and a major PITA.

Agreed, but the 'auto' thing ultimately comes from C, not C++.

totally different from it's current D counterpart.

No, it's not. It's a storage class in C++, *not* a type inference keyword. It's just that it's a storage class that in modern times is only used in the context of type inference. I think 'var' makes much more sense for dynamically typed languages. Still, I just learned that C# 3.0 is going to use it. What is the C# 3.0 type inference syntax? How does it deal with type inference of constants?
Jul 27 2006
next sibling parent Nils Hensel <nils.hensel web.de> writes:
Don Clugston schrieb:
 No, the idea is *not* to have a type inference keyword, but instead only 
 specify the storage class:
 
 static a = 7;
 const b = 7;
 auto  c = 7;
 
 Now 'a' is a variable, just as much 'c' is.
 
 Are you proposing that you'd have to type:
 
 static var x =  func(7);

 ? Surely not. 'const var' would be an abomination!

I never said variables and constants should be treated the same.
 The problem is, there's no storage class for local variables. In C/C++, 
 there is, and it's called 'auto', but it's extremely rarely used in 
 normal code. 'local' is perhaps the most natural name.

have to carry this ugly legacy. The unexpressiveness of "auto" might be my whole problem with type inference as it is. Using storage classes for detection is a rather clever idea.
 I just don't like the idea that 'var' would mean "local non-static 
 variable". "Variable" is a much broader category than "local variable".

I believe most people think of when they hear "variable".
 I hope that one day D also gets explicit thread-local variables. They 
 would need a seperate storage class.

 Agreed, but the 'auto' thing ultimately comes from C, not C++.

totally different from it's current D counterpart.

No, it's not. It's a storage class in C++, *not* a type inference keyword. It's just that it's a storage class that in modern times is only used in the context of type inference.

are better expressed in a different way.
 I think 'var' makes much more sense for dynamically typed languages. 
 Still, I just learned that C# 3.0 is going to use it.
 What is the C# 3.0 type inference syntax? How does it deal with type 
 inference of constants?

what you described above and that "const" does not get a "var". But it's just a guess. Regards, Nils
Jul 28 2006
prev sibling parent Sean Kelly <sean f4.ca> writes:
Don Clugston wrote:
 
 No, the idea is *not* to have a type inference keyword, but instead only 
 specify the storage class:
 
 static a = 7;
 const b = 7;
 auto  c = 7;
 
 Now 'a' is a variable, just as much 'c' is.

So long as the storage class is required, I'm all for it. This seems more consistent than what we have now.
 I hope that one day D also gets explicit thread-local variables. They 
 would need a seperate storage class.

I proposed this a while back and no one responded, so I went and added thread-local storage to Ares. But it would be much nicer to have this as a language feature.
 No, it's not. It's a storage class in C++, *not* a type inference 
 keyword. It's just that it's a storage class that in modern times is 
 only used in the context of type inference.

The things you learn. I don't think I've ever seen 'auto' used in a C or C++ program, though I've come across 'register' quite a bit. Sean
Jul 28 2006
prev sibling next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 25 Jul 2006 10:17:13 -0700, kris <foo bar.com> wrote:
 Don has a good point: changing to "var" would cause conflict with  
 existing variable-names.

 Chad et. al. also have a good point about the conflict regarding static  
 opCall() (via the lack of a "new" keyword). I suspect many people find  
 the use of "new" to be indicative of allocation, and breaking this  
 consistency may have a detrimental effect? Further, it was noted that a  
 missing "new" can only be used at the instantiation site -- not at the  
 class decl -- thus, D would be losing an existing feature.

 I suspect you could count the current number of raii-class uses on a few  
 hands, whereas the use of "auto" for implied-type is pretty darned  
 popular -- and rightly so, since it's really very, very useful. Changing  
 the raii style to use a different keyword, whilst retaining implied-type  
 "auto" would be an almost imperceptible change?

 Thus, it would appear to make sense to retain "auto" for implied-type,  
 and introduce something *else* for automatic cleanup at end-of-scope  
 (and also as a class attribute). how about reusing the "scope" keyword?

 void main()
 {
    auto i = 10;
    auto foo = new Foo;
    auto scope bar = new Bar;
    auto scope wumpus = new Wumpus;
 }

 class Foo {}

 class Bar {}

 scope class Wumpus {}

I say lets keep 'auto' for auto type inference (for the reasons you and Don mention) I like the use of scope at class decl. But, I prefer the no keyword approach at instantiation. So, allow me to suggest this as a 3rd option. - 'scope' at class decl. - no keyword at instatiation. Reasoning: 'new' implies heap allocation to me. It would be beneficial to allow the compiler to allocate an RAII type in any way it wants, perhaps stack allocating it. Removing 'new' removes the implied heap allocation allowing the compiler to allocate however it likes. I don't see the utility in static opCall, I say abolish/remove it. Non-static opCall on the other hand can be quite useful. Regan
Jul 25 2006
next sibling parent reply Chad J <gamerChad _spamIsBad_gmail.com> writes:
Regan Heath wrote:
 
 
 I say lets keep 'auto' for auto type inference (for the reasons you and  
 Don mention)
 
 I like the use of scope at class decl. But, I prefer the no keyword  
 approach at instantiation. So, allow me to suggest this as a 3rd option.
 
 - 'scope' at class decl.
 - no keyword at instatiation.
 
 Reasoning:
 
 'new' implies heap allocation to me. It would be beneficial to allow 
 the  compiler to allocate an RAII type in any way it wants, perhaps 
 stack  allocating it. Removing 'new' removes the implied heap allocation 
 allowing  the compiler to allocate however it likes.
 

I disagree. If you want the compiler to be able to optimize by using stack allocation instead of heap allocation, then let it do that with the new keyword. I'm assuming the program's behaviour would be the same in either case, so it wouldn't matter to me. If you want stack allocation then how about scope A a = A(); It keeps the concepts of scope and allocation seperate. Scope is not allocation. For instance, if the function is inlined then something allocated on the stack should live longer than the scope of the function. The only exceptions I can think of are if the compiler forbids inlining of such functions (possibly inefficient) or there is a scope guarantee, in which case you want scope AND stack alloc. Or maybe I just don't understand inlining (hope not!).
 I don't see the utility in static opCall, I say abolish/remove it.  
 Non-static opCall on the other hand can be quite useful.
 
 Regan

Please don't abolish/remove it. At least not until you have convinced me that it is totally useless. I really don't like the idea of dropping a language feature just for the sake of having a particular syntax that, IMO, is not intuitive. As I said in the 1.0 thread, A a = A(); looks to me like anything but a scoped instanciation; I'd rather have a keyword (like scope) to indicate what it is in an explicit way. From my previous post about this:
 I like being able to use types as functions.
 Here's one example where I do something similar to what you'd use nested
functions for, but better - my forward referencing woes go away.
 
 class F
 {
     int result;
     int tempVar1;
 
     static int opCall( int x )
     {
         F f = new F(x);
         int result = f.result;
         delete f;
         return result;
     }
 
     this( int x )
     {
         internalFunc1();
         // do stuff
     }
 
     private void internalFunc1()
     {
         if ( maybe )
             internalFunc2();
         else return;
     }
 
     private void internalFunc2()
     {
         if ( maybe )
             internalFunc1();
         else return;
     }
 }
 
 void main()
 {
     int x = 42;
     x = F(x);
 }
 
 Under the hood, it may also behave differently than nested functions, which
could be advantageous.  I'm not sure that it is advantageous, but options are
always nice.
 
 That and you can make nice syntax sugars for alternative memory management
methods like freelists, without messing with overriding 'new()'. 

I do like using the scope keyword for this btw. It seems quite consistant with D's meaning of 'scope'.
Jul 25 2006
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 25 Jul 2006 23:28:24 -0400, Chad J  
<gamerChad _spamIsBad_gmail.com> wrote:
 Regan Heath wrote:
   I say lets keep 'auto' for auto type inference (for the reasons you  
 and  Don mention)
  I like the use of scope at class decl. But, I prefer the no keyword   
 approach at instantiation. So, allow me to suggest this as a 3rd option.
  - 'scope' at class decl.
 - no keyword at instatiation.
  Reasoning:
  'new' implies heap allocation to me. It would be beneficial to allow  
 the  compiler to allocate an RAII type in any way it wants, perhaps  
 stack  allocating it. Removing 'new' removes the implied heap  
 allocation allowing  the compiler to allocate however it likes.

I disagree. If you want the compiler to be able to optimize by using stack allocation instead of heap allocation, then let it do that with the new keyword.

You miss-understand. I don't want stack allocation at all. I'm saying 2 things: 1. 'new' implies heap allocation 2. lack of 'new' implies _nothing_ about allocation. The result of which is that the compiler is not _required_ to heap allocate but can allocate in some other fashion.
 I'm assuming the program's behaviour would be the same in either case,  
 so it wouldn't matter to me.

 If you want stack allocation then how about
 scope A a = A();

 It keeps the concepts of scope and allocation seperate.

It's no different to this: A a = A(); which says _nothing_ about allocation. It implies only that 'a' will be collected at the end of scope. The compiler is FREE to allocate however it wants. That _may_ be stack allocation, it _may_ not. In comparison this: A a = new A(); currently 'implies' heap allocation. That's all I was saying. I'm not suggesting stack allocation, I'm suggesting that removing 'new' allows the compiler to allocate however it wants. You're suggesting 'new' could allocate on the stack, I think that would be unexpected to say the least.
 Scope is not allocation.

Correct. I never said it was. The ability to stack allocate is a by product of removing 'new' nothing else.
 I don't see the utility in static opCall, I say abolish/remove it.   
 Non-static opCall on the other hand can be quite useful.
  Regan

Please don't abolish/remove it. At least not until you have convinced me that it is totally useless.

Convince you.. I don't have to convince you, only Walter. Likewise you have to convince Walter. ;0)
 I really don't like the idea of dropping a language feature just for the  
 sake of having a particular syntax that, IMO, is not intuitive.

It's the same syntax you see in C++ for a class that has it's destructor called at the end of the scope. That, to me, makes it intuitive. For what reason do you find it un-intuitive?
  From my previous post about this:
 I like being able to use types as functions.
 Here's one example where I do something similar to what you'd use  
 nested functions for, but better - my forward referencing woes go away.
  class F
 {
     int result;
     int tempVar1;
      static int opCall( int x )
     {
         F f = new F(x);
         int result = f.result;
         delete f;
         return result;
     }
      this( int x )
     {
         internalFunc1();
         // do stuff
     }
      private void internalFunc1()
     {
         if ( maybe )
             internalFunc2();
         else return;
     }
      private void internalFunc2()
     {
         if ( maybe )
             internalFunc1();
         else return;
     }
 }
  void main()
 {
     int x = 42;
     x = F(x);
 }
  Under the hood, it may also behave differently than nested functions,  
 which could be advantageous.  I'm not sure that it is advantageous, but  
 options are always nice.
  That and you can make nice syntax sugars for alternative memory  
 management methods like freelists, without messing with overriding  
 'new()'.


What's the point of using static opCall here, as opposed to a normal static method or even a free function? What problem does it solve? What new technique or method does it allow?
 I do like using the scope keyword for this btw.  It seems quite  
 consistant with D's meaning of 'scope'.

It's not bad but it's my 2nd choice currently. Regan
Jul 25 2006
next sibling parent reply "Chris Miller" <chris dprogramming.com> writes:
On Wed, 26 Jul 2006 00:13:53 -0400, Regan Heath <regan netwin.co.nz> wrote:
 1. 'new' implies heap allocation

Except when it doesn't. I'm talking about overloaded 'new' If Object`s were given 2 default new() implmentations, one that does the current allocation, and another that allows you to specify a buffer (also so that every Joe who wants this doesn't have to derive from the class to provide it). When RAII is involved, it can choose which version of new() to use (implementaion defined), using stack or not.
Jul 25 2006
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 26 Jul 2006 00:23:41 -0400, Chris Miller <chris dprogramming.com>  
wrote:
 On Wed, 26 Jul 2006 00:13:53 -0400, Regan Heath <regan netwin.co.nz>  
 wrote:
 1. 'new' implies heap allocation

Except when it doesn't. I'm talking about overloaded 'new' If Object`s were given 2 default new() implmentations, one that does the current allocation, and another that allows you to specify a buffer (also so that every Joe who wants this doesn't have to derive from the class to provide it). When RAII is involved, it can choose which version of new() to use (implementaion defined), using stack or not.

You're describing 'placement' new, yes? http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=160&rl=1 I dont think D has placement new, at least not a syntax for it like C++. I could be wrong. You're right in that if D were to get placement new using the C++ syntax then the suggested RAII syntax (removing 'new') would make it impossible to declare an RAII class using placement new. But, it appears that placement new in D is done with a custom allocator and not a special syntax? http://www.digitalmars.com/d/memory.html#newdelete You coud write a custom allocator which would calculate offsets into pre-allocated memory returning that address for each allocation. Essentially placement new without the special syntax. Has this topic come up before? What was Walters comment on it? I don't recall a discussion on it, I did a quick search and didn't turn up anything specific. I wonder, does placement new in D have the same restrictions as in C++? i.e. cannot use stack memory, requires explicit 'delete'. I wonder what constraints the RAII implementation in D puts on how objects are allocated. It's possible they can't be allocated on the stack .. I seem to recall Walter saying he'd like to go there, eventually, but I might be imagining things. Regan
Jul 25 2006
parent reply "Chris Miller" <chris dprogramming.com> writes:
On Wed, 26 Jul 2006 01:23:53 -0400, Regan Heath <regan netwin.co.nz> wro=
te:

 On Wed, 26 Jul 2006 00:23:41 -0400, Chris Miller  =

 <chris dprogramming.com> wrote:
 On Wed, 26 Jul 2006 00:13:53 -0400, Regan Heath <regan netwin.co.nz> =


 wrote:
 1. 'new' implies heap allocation

Except when it doesn't. I'm talking about overloaded 'new' If Object`s were given 2 default new() implmentations, one that does =


 the current allocation, and another that allows you to specify a buff=


 (also so that every Joe who wants this doesn't have to derive from th=


 class to provide it). When RAII is involved, it can choose which  =


 version of new() to use (implementaion defined), using stack or not.

You're describing 'placement' new, yes? http://www.informit.com/guides/content.asp?g=3Dcplusplus&seqNum=3D160&=

 I dont think D has placement new, at least not a syntax for it like C+=

 I could be wrong.

 You're right in that if D were to get placement new using the C++ synt=

 then the suggested RAII syntax (removing 'new') would make it impossib=

 to declare an RAII class using placement new. But, it appears that  =

 placement new in D is done with a custom allocator and not a special  =

 syntax?

 http://www.digitalmars.com/d/memory.html#newdelete

I hadn't thought of 'placement' new but this page is what I was referrin= g = to. Scroll down to "Allocating Class Instances On The Stack" to see what= I = meant. Different uses of 'new' (RAII/regular) could call different new()= s, = which doesn't imply heap.
Jul 27 2006
parent Sean Kelly <sean f4.ca> writes:
Chris Miller wrote:
 On Wed, 26 Jul 2006 01:23:53 -0400, Regan Heath <regan netwin.co.nz> wrote:
 http://www.digitalmars.com/d/memory.html#newdelete

I hadn't thought of 'placement' new but this page is what I was referring to. Scroll down to "Allocating Class Instances On The Stack" to see what I meant. Different uses of 'new' (RAII/regular) could call different new()s, which doesn't imply heap.

This is placement new--the parameter to new specifies the location where the object will be constructed. Sean
Jul 27 2006
prev sibling next sibling parent reply Chad J <gamerChad _spamIsBad_gmail.com> writes:
Regan Heath wrote:
 On Tue, 25 Jul 2006 23:28:24 -0400, Chad J  
 <gamerChad _spamIsBad_gmail.com> wrote:
 
 Regan Heath wrote:

   I say lets keep 'auto' for auto type inference (for the reasons 
 you  and  Don mention)
  I like the use of scope at class decl. But, I prefer the no 
 keyword   approach at instantiation. So, allow me to suggest this as 
 a 3rd option.
  - 'scope' at class decl.
 - no keyword at instatiation.
  Reasoning:
  'new' implies heap allocation to me. It would be beneficial to 
 allow  the  compiler to allocate an RAII type in any way it wants, 
 perhaps  stack  allocating it. Removing 'new' removes the implied 
 heap  allocation allowing  the compiler to allocate however it likes.

I disagree. If you want the compiler to be able to optimize by using stack allocation instead of heap allocation, then let it do that with the new keyword.

You miss-understand. I don't want stack allocation at all. I'm saying 2 things: 1. 'new' implies heap allocation 2. lack of 'new' implies _nothing_ about allocation. The result of which is that the compiler is not _required_ to heap allocate but can allocate in some other fashion.

That's actually what I thought you meant, though I am probably creating a false dichotomy - stack vs heap.
 I'm assuming the program's behaviour would be the same in either 
 case,  so it wouldn't matter to me.

 If you want stack allocation then how about
 scope A a = A();

 It keeps the concepts of scope and allocation seperate.

It's no different to this: A a = A(); which says _nothing_ about allocation. It implies only that 'a' will be collected at the end of scope. The compiler is FREE to allocate however it wants. That _may_ be stack allocation, it _may_ not. In comparison this: A a = new A(); currently 'implies' heap allocation. That's all I was saying. I'm not suggesting stack allocation, I'm suggesting that removing 'new' allows the compiler to allocate however it wants. You're suggesting 'new' could allocate on the stack, I think that would be unexpected to say the least.

I did intend to convey that the 'new' keyword could have this ambiguity, but under one condition - that it not change the behaviour of the program. If you need something more hardcore than that, something that causes undefined behaviour, I ask that it not be at the expense of current features.
 Scope is not allocation.

Correct. I never said it was. The ability to stack allocate is a by product of removing 'new' nothing else.
 I don't see the utility in static opCall, I say abolish/remove it.   
 Non-static opCall on the other hand can be quite useful.
  Regan

Please don't abolish/remove it. At least not until you have convinced me that it is totally useless.

Convince you.. I don't have to convince you, only Walter. Likewise you have to convince Walter. ;0)

True, you are not required to convince me of anything. It was a request. You seem to have some good reasons for prefering this syntax, so please enlighten me. It's kind of a helpfulness thing; saves me some grief from having a feature removed that I like. If I agree with you, there is no grief, only joy :).
 I really don't like the idea of dropping a language feature just for 
 the  sake of having a particular syntax that, IMO, is not intuitive.

It's the same syntax you see in C++ for a class that has it's destructor called at the end of the scope. That, to me, makes it intuitive. For what reason do you find it un-intuitive?

I do not originate from C++, more like C#/Java. I do know some C++ though, and most of my experiences with it have been frustrating bad ones. Anyhow, before I go on that tangent, not everyone is a C++ programmer. I say it's unintuitive because it is implicit - it provides no explicit information to the reader. Since the absence of anything explicit gives no information, you might as well use the keyword asdfqwertok. Even that gives more information than a blank space. For a D newbie reading code, having a keyword is good because it gives them a keyword to search the spec for. Better yet if it is 'scope', because that gives them an idea of where to look. This is also one of those things that is used seldom enough that the succinctness gained from implicit things is only slightly helpful. In a nutshell: assume a programmer of undefined language background, and I believe 'scope' will be much more informative (and therefore intuitive) than a blank space.
  From my previous post about this:

 I like being able to use types as functions.
 Here's one example where I do something similar to what you'd use  
 nested functions for, but better - my forward referencing woes go away.
  class F
 {
     int result;
     int tempVar1;
      static int opCall( int x )
     {
         F f = new F(x);
         int result = f.result;
         delete f;
         return result;
     }
      this( int x )
     {
         internalFunc1();
         // do stuff
     }
      private void internalFunc1()
     {
         if ( maybe )
             internalFunc2();
         else return;
     }
      private void internalFunc2()
     {
         if ( maybe )
             internalFunc1();
         else return;
     }
 }
  void main()
 {
     int x = 42;
     x = F(x);
 }
  Under the hood, it may also behave differently than nested 
 functions,  which could be advantageous.  I'm not sure that it is 
 advantageous, but  options are always nice.
  That and you can make nice syntax sugars for alternative memory  
 management methods like freelists, without messing with overriding  
 'new()'.


What's the point of using static opCall here, as opposed to a normal static method or even a free function?

Why not a normal static method? - implementation hiding. Why not a free function? - I'm assuming you mean a normal function declared at module scope. It allows you to have multiple functions with access to the same non-static variables (member variables). I suppose this is usually accomplished with nested functions, or OOP that can't do implementation hiding. Doing it this way allows me to avoid forward referencing issues and also gives me more options about how my code behaves.
 What problem does it solve?

Annoyance from forward referencing in nested functions, but that's just one. Maybe a small degree of implementation hiding for memory management, though I haven't tried this enough to demonstrate it. It is not really a solution. It is a technique, a syntax sugar, or just an easy way to get D to do things you would not ordinarily make it do.
 What new technique or method does it allow?

Multiple functions using the same non-static variables with no need for forward referencing and possible code behaviour tweaks, etc yadda yadda. I admit it's not horribly important, but I don't think that this choice of syntax is either. Most of all, I like it. *sigh* those were long winded answers, sorry about that.
 
 I do like using the scope keyword for this btw.  It seems quite  
 consistant with D's meaning of 'scope'.

It's not bad but it's my 2nd choice currently. Regan

Care to explain why static opCall is a hack and/or not useful outside of RAII or struct constructors?
Jul 26 2006
parent reply "Regan Heath" <regan netwin.co.nz> writes:
 Please don't abolish/remove it.  At least not until you have  
 convinced  me that it is totally useless.

Likewise you have to convince Walter. ;0)

True, you are not required to convince me of anything. It was a request. You seem to have some good reasons for prefering this syntax, so please enlighten me.

I've already said.. I think it's intuitive because it 'looks' like a class declared on the stack, as in C++ and like those it will be destroyed at the end of scope. Your counter argument is that not everyone is a C++ programmer, correct? In which case, read on..
 I really don't like the idea of dropping a language feature just for  
 the  sake of having a particular syntax that, IMO, is not intuitive.

destructor called at the end of the scope. That, to me, makes it intuitive. For what reason do you find it un-intuitive?

I do not originate from C++, more like C#/Java. I do know some C++ though, and most of my experiences with it have been frustrating bad ones. Anyhow, before I go on that tangent, not everyone is a C++ programmer.

I come from a C background. I have done a little C++, a little Java and very little C#.
 I say it's unintuitive because it is implicit - it provides no explicit  
 information to the reader.  Since the absence of anything explicit gives  
 no information, you might as well use the keyword asdfqwertok.  Even  
 that gives more information than a blank space.

The absence of 'new' gives us the required information. You are required to know what the absense of 'new' _means_ just like you are required to know what keyword X means in any given context. In short, some knowledge of programming in D is required to program in D. To expand on why I think it's intuitive let look at 2 scenarios, first the C++ programmer trying D. Likely their first program involving classes will look like this: class A { int a; } void main() { A a = A(); writefln(a.a); } currently, this crashes with an access violation. Add the new RAII syntax and not only does it not crash, but it behaves just like a C++ program would with A being destroyed at the end of scope. Now, take a Java/C# programmer, their first program with classes will be: class A { int a; } void main() { A a = new A(); writefln(a.a); } No crash, and the behaviour they expect. Then imagine the same programmers looking at each others code, the C++ programmer will understand 'new' to indicate heap allocation and the Java/C# programmer will need to ask the C++ programmer what the absense of 'new' means, he'll reply that the class is destroyed at the end of scope. He might also say it's stack allocated, but that's fine, both of them have something to learn, and it has no effect on the way the program behaves. Simple, intuitive and elegant no matter what your background. Of course, if you're a Java/C# programmer you have to 'learn' what the absense of 'new' means. Both have to learn that D might not stack allocate the RAII class instance. If we use a 'scope' keyword then both sets of programmers have some learning to do. It's not much worse, but this makes it my 2nd choice.
 For a D newbie reading code, having a keyword is good because it gives  
 them a keyword to search the spec for. Better yet if it is 'scope',  
 because that gives them an idea of where to look.  This is also one of  
 those things that is used seldom enough that the succinctness gained  
 from implicit things is only slightly helpful.

The C++ programmer will already know what it does. The Java/C++ programmer will search for 'new' (because it's absent). In either case they'll find the docs on RAII at the same time as they find the docs on 'new'.
 In a nutshell: assume a programmer of undefined language background, and  
 I believe 'scope' will be much more informative (and therefore  
 intuitive) than a blank space.

I've assumed programmers from 2 types of background above, I still think removing 'new' is better than adding 'scope'.
  From my previous post about this:

 I like being able to use types as functions.
 Here's one example where I do something similar to what you'd use   
 nested functions for, but better - my forward referencing woes go  
 away.
  class F
 {
     int result;
     int tempVar1;
      static int opCall( int x )
     {
         F f = new F(x);
         int result = f.result;
         delete f;
         return result;
     }
      this( int x )
     {
         internalFunc1();
         // do stuff
     }
      private void internalFunc1()
     {
         if ( maybe )
             internalFunc2();
         else return;
     }
      private void internalFunc2()
     {
         if ( maybe )
             internalFunc1();
         else return;
     }
 }
  void main()
 {
     int x = 42;
     x = F(x);
 }
  Under the hood, it may also behave differently than nested  
 functions,  which could be advantageous.  I'm not sure that it is  
 advantageous, but  options are always nice.
  That and you can make nice syntax sugars for alternative memory   
 management methods like freelists, without messing with overriding   
 'new()'.


static method or even a free function?

Why not a normal static method? - implementation hiding.

I'm assuming this defintion: http://en.wikipedia.org/wiki/Information_hiding I'm not sure I follow your logic, did you mean "encapsulation" instead? If you did mean "information hiding" then it seems to me that using opCall is a design decision, just as using a method called "Bob" would be. The advantage to using "Bob" is that you can define an 'stable' interface eg. interface MyImplementation { int Bob(int x); } and in that way protect your code against changes in implementation. In short, this is a better "information hiding" solution than using static opCall.
 Why not a free function? - I'm assuming you mean a normal function  
 declared at module scope.

Yes.
 It allows you to have multiple functions with access to the same  
 non-static variables (member variables).

What does? _static_ opCall does *not* have access to non-static variables, it can only access static variables. Static methods and variables are very similar to module level variables. The difference being how to access them (class name prefix) and where they are declared (inside the class instead of at module level). You can replace static methods and variables with module level ones quite easily.
 I suppose this is usually accomplished with nested functions, or OOP  
 that can't do implementation hiding.

I'm obviously not following your point here.. can you elaborate, perhaps another example?
 Doing it this way allows me to avoid forward referencing issues

What forward referencing issues does the code above have?
 and also gives me more options about how my code behaves.

What options? example?
 What problem does it solve?

Annoyance from forward referencing in nested functions, but that's just one. Maybe a small degree of implementation hiding for memory management, though I haven't tried this enough to demonstrate it. It is not really a solution. It is a technique, a syntax sugar, or just an easy way to get D to do things you would not ordinarily make it do.

So far: - I'm not seeing the forward reference issue(s) - It seems like a worse way to implement information hiding (than an interface and method).
 What new technique or method does it allow?

Multiple functions using the same non-static variables with no need for forward referencing and possible code behaviour tweaks, etc yadda yadda. I admit it's not horribly important, but I don't think that this choice of syntax is either. Most of all, I like it.

I *like* non-static opCall, I can see benefits to that. But, so far, static opCall seems to be fairly useless to me.
 *sigh* those were long winded answers, sorry about that.

No worries. Long winded tends to imply more information and that's not a bad thing.
 I do like using the scope keyword for this btw.  It seems quite   
 consistant with D's meaning of 'scope'.

Regan

Care to explain why static opCall is a hack and/or not useful outside of RAII or struct constructors?

I'm trying, by learning when, where and why you use it. I can't think of a place where _I_ would use it (which is why I think it's not useful). It's only a 'hack' when used with a struct to emulate a constructor. Strangely that 'hack' is the only vaguely good use I've seen for a *static* opCall. Regan
Jul 26 2006
parent reply Chad J <gamerChad _spamIsBad_gmail.com> writes:
Regan Heath wrote:
 

 I've already said.. I think it's intuitive because it 'looks' like a 
 class  declared on the stack, as in C++ and like those it will be 
 destroyed at  the end of scope. Your counter argument is that not 
 everyone is a  C++ programmer, correct? In which case, read on..
 

 
 I come from a C background. I have done a little C++, a little Java and  
 very little C#.
 
 
 The absence of 'new' gives us the required information. You are 
 required  to know what the absense of 'new' _means_ just like you are 
 required to  know what keyword X means in any given context. In short, 
 some knowledge  of programming in D is required to program in D.

I agree, the point is to make it easier to obtain that knowledge while learning.
 
 To expand on why I think it's intuitive let look at 2 scenarios, first 
 the  C++ programmer trying D. Likely their first program involving 
 classes will  look like this:
 
 class A {
   int a;
 }
 
 void main() {
   A a = A();
   writefln(a.a);
 }
 
 currently, this crashes with an access violation. 

Actually, it doesn't compile. main.d(6): function expected before (), not A of type main.A main.d(6): cannot implicitly convert expression ((A)()) of type int to main.A Maybe not the best error messages for this case, but better than an access violation.
 Add the new RAII 
 syntax  and not only does it not crash, but it behaves just like a C++ 
 program  would with A being destroyed at the end of scope.

I hear that such syntax, in C++, means that 'A' will be stack allocated, which AFAIK does not imply RAII. One example I can think of that would break RAII is if the function gets inlined, then the stack allocated object may not be deleted until some point outside of the scope's end. It will /probably/ be deleted at the end of the function that the enclosing function was inlined into. I could be wrong about that though. Also, does that C++ syntax allow class references to leak into code that is executed after the class is deleted?
 
 Now, take a Java/C# programmer, their first program with classes will be:
 
 class A {
   int a;
 }
 
 void main() {
   A a = new A();
   writefln(a.a);
 }
 
 No crash, and the behaviour they expect.
 
 Then imagine the same programmers looking at each others code, the  C++ 
 programmer will understand 'new' to indicate heap allocation and the  
 Java/C# programmer will need to ask the C++ programmer what the absense 
 of  'new' means, he'll reply that the class is destroyed at the end of 
 scope.  He might also say it's stack allocated, but that's fine, both of 
 them have  something to learn, and it has no effect on the way the 
 program behaves.

That learning process would be nice, but it assumes an extra programmer being around. As I learn D, I am alone. Either I go to the spec or I ask on the newsgroup. I'm not sure how many others are in the same situation. I've explained below why I still don't think it's very obvious, which means more potential newsgroup asking. That doesn't bug me too much though.
 
 Simple, intuitive and elegant no matter what your background. Of 
 course,  if you're a Java/C# programmer you have to 'learn' what the 
 absense of  'new' means. Both have to learn that D might not stack 
 allocate the RAII  class instance.
 
 If we use a 'scope' keyword then both sets of programmers have some  
 learning to do. It's not much worse, but this makes it my 2nd choice.
 

"Both have to learn that D might not stack allocate the RAII class instance." "If we use a 'scope' keyword then both sets of programmers have some learning to do." If they both have learning to do anyways, why not just have them learn 'scope'? I suppose it wouldn't be too bad otherwise, except for one problem: The unfortunate C++ programmer's program worked as expected. I say problem and unfortunate, because they may just assume that D behaves like C++ in all of the corner cases, and if I'm correct about the RAII vs stack alloc above, it may not.
 For a D newbie reading code, having a keyword is good because it 
 gives  them a keyword to search the spec for. Better yet if it is 
 'scope',  because that gives them an idea of where to look.  This is 
 also one of  those things that is used seldom enough that the 
 succinctness gained  from implicit things is only slightly helpful.

The C++ programmer will already know what it does. The Java/C++ programmer will search for 'new' (because it's absent). In either case they'll find the docs on RAII at the same time as they find the docs on 'new'.

Searching for 'new' is a good idea. What if they don't think of that? The only reason I would associate the absence of 'new' with allocation is because of the talk from C++ programmers on this newsgroup. Otherwise it's some kind of wacky cool feature of D that they have not read about yet (as it is now!). This is why I prefer 'scope' - it would make scope, unambiguously, THE keyword to search for to find out what's going on.
 
 In a nutshell: assume a programmer of undefined language background, 
 and  I believe 'scope' will be much more informative (and therefore  
 intuitive) than a blank space.

I've assumed programmers from 2 types of background above, I still think removing 'new' is better than adding 'scope'.

That's fine as long as you clear up the two things: - What tells a non-C++ coder to look up 'new'? (besides another coder) - The possible assumption by a C++ coder that RAII syntax means stack allocation. (and subsequent whammy when they hit a pointy corner case) Proving that there are no corner cases in 'stack allocation implies RAII' or me being wrong about that meaning in C++ should clear up that second one.
   What's the point of using static opCall here, as opposed to a 
 normal   static method or even a free function?

Why not a normal static method? - implementation hiding.

I'm assuming this defintion: http://en.wikipedia.org/wiki/Information_hiding I'm not sure I follow your logic, did you mean "encapsulation" instead? If you did mean "information hiding" then it seems to me that using opCall is a design decision, just as using a method called "Bob" would be. The advantage to using "Bob" is that you can define an 'stable' interface eg. interface MyImplementation { int Bob(int x); } and in that way protect your code against changes in implementation. In short, this is a better "information hiding" solution than using static opCall.
 Why not a free function? - I'm assuming you mean a normal function  
 declared at module scope.

Yes.
 It allows you to have multiple functions with access to the same  
 non-static variables (member variables).

What does? _static_ opCall does *not* have access to non-static variables, it can only access static variables. Static methods and variables are very similar to module level variables. The difference being how to access them (class name prefix) and where they are declared (inside the class instead of at module level). You can replace static methods and variables with module level ones quite easily.
 I suppose this is usually accomplished with nested functions, or OOP  
 that can't do implementation hiding.

I'm obviously not following your point here.. can you elaborate, perhaps another example?
 Doing it this way allows me to avoid forward referencing issues

What forward referencing issues does the code above have?
 and also gives me more options about how my code behaves.

What options? example?
 What problem does it solve?

Annoyance from forward referencing in nested functions, but that's just one. Maybe a small degree of implementation hiding for memory management, though I haven't tried this enough to demonstrate it. It is not really a solution. It is a technique, a syntax sugar, or just an easy way to get D to do things you would not ordinarily make it do.

So far: - I'm not seeing the forward reference issue(s) - It seems like a worse way to implement information hiding (than an interface and method).
 What new technique or method does it allow?

Multiple functions using the same non-static variables with no need for forward referencing and possible code behaviour tweaks, etc yadda yadda. I admit it's not horribly important, but I don't think that this choice of syntax is either. Most of all, I like it.

I *like* non-static opCall, I can see benefits to that. But, so far, static opCall seems to be fairly useless to me.
 *sigh* those were long winded answers, sorry about that.

No worries. Long winded tends to imply more information and that's not a bad thing.
 I do like using the scope keyword for this btw.  It seems quite   
 consistant with D's meaning of 'scope'.

It's not bad but it's my 2nd choice currently. Regan

Care to explain why static opCall is a hack and/or not useful outside of RAII or struct constructors?

I'm trying, by learning when, where and why you use it. I can't think of a place where _I_ would use it (which is why I think it's not useful). It's only a 'hack' when used with a struct to emulate a constructor. Strangely that 'hack' is the only vaguely good use I've seen for a *static* opCall. Regan

OK I think I have not explained my example very well. First I'll simplify my original example and try harder to explain. I've added comments this time. Here it is: import std.stdio; // class used as a function class f { int result; int tempVar1; // this is your non-static variable static int opCall( int x ) { // what do you know, not so 'static' after all! f instance = new f(x); int result = instance.result; // cleanup delete instance; return result; } this( int x ) { // If this were a function with nested functions, // then the main execution would occur here. result = x + internalFunc(); } // this is a non-static function int internalFunc() { return 314; } } void main() { int x = 42; x = f(x); writefln(x); } Now I'll rewrite it into a free function: import std.stdio; int f( int x ) { // Error! internalFunc is not defined. return x + internalFunc(); // oh but here it is... nested functions don't allow this int internalFunc() { return 314; } } void main() { int x = 42; x = f(x); writefln(x); } In a trivial case like this all you have to do is move the nested function internalFunc to the top. In other cases though, where you want to be able to places the functions where they intuitively belong, this becomes annoying. This is that forward referencing issue I was talking about. Also, if 'f' were derived from another class, then the code executed in f's constructor would have access to the super class's members. That's more to do with OOP, but it's all hidden behind a static opCall. I suppose you could use a module function to construct and delete a private class that gets used for it's own scope and inheritance. I worry that I am missing some detail that stopped me from just doing that before. Sean, perhaps you could share some of your uses for static opCall since I'm doing such a bad job at this? Only slightly related - I wonder if D's 'new' even implies heap allocation as it is. That might just be a dmd thing, but I am looking in the spec at Classes -> ctors/dtors, and it doesn't say where they get allocated. Maybe someone who is good at searching the spec can find if it says where classes get allocated? My thought, as xs0 has mentioned as well, is that 'new' could be defined independant of those implementation details. For example, just say that 'new' will allocate a class instance, and that the instance will be cleaned up only after there are no more references to that class. The only exception being explicit deletion. Since RAII gaurantees, AFAIK, that there are no references leaked into code that gets executed after the scope is exited, then stack allocation would work here. I'm finding it hard to imagine code that would require an object to be in the heap's address range or in the stack's address range. xs0 says there are other cases in which a class can be allocated on the stack without breaking the gaurantees of no premature deletion, and I wonder what they are.
Jul 28 2006
next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Fri, 28 Jul 2006 04:44:44 -0400, Chad J  
<gamerChad _spamIsBad_gmail.com> wrote:
 Regan Heath wrote:

 I've already said.. I think it's intuitive because it 'looks' like a  
 class  declared on the stack, as in C++ and like those it will be  
 destroyed at  the end of scope. Your counter argument is that not  
 everyone is a  C++ programmer, correct? In which case, read on..

  I come from a C background. I have done a little C++, a little Java  
 and  very little C#.
   The absence of 'new' gives us the required information. You are  
 required  to know what the absense of 'new' _means_ just like you are  
 required to  know what keyword X means in any given context. In short,  
 some knowledge  of programming in D is required to program in D.

I agree, the point is to make it easier to obtain that knowledge while learning.
  To expand on why I think it's intuitive let look at 2 scenarios, first  
 the  C++ programmer trying D. Likely their first program involving  
 classes will  look like this:
  class A {
   int a;
 }
  void main() {
   A a = A();
   writefln(a.a);
 }
  currently, this crashes with an access violation.

Actually, it doesn't compile. main.d(6): function expected before (), not A of type main.A main.d(6): cannot implicitly convert expression ((A)()) of type int to main.A Maybe not the best error messages for this case, but better than an access violation.

Err.. oops.. my example was in fact assuming the new "omit 'new'" syntax was added, then I went and confused it with: A a; writefln(a.a); which is actually what a C++ programmer would write to allocate a class on the stack and have it destroyed at end of scope. The syntax: A a; writefln(a.a); will crash, the new syntax isn't invloved at all, sorry.
 Add the new RAII syntax  and not only does it not crash, but it behaves  
 just like a C++ program  would with A being destroyed at the end of  
 scope.

I hear that such syntax, in C++, means that 'A' will be stack allocated, which AFAIK does not imply RAII.

No, but the resulting behaviour is almost identical. In C++ the syntax: A a; causes 'a' to be allocated on the stack and the destructor called at end of scope. Apart from being allocated on the stack (which Walter indicates in the docs is something he plans to implement at a later date for 'auto') it's identical to the behaviour of D's 'auto'. http://www.digitalmars.com/d/memory.html#stackclass "To have a class allocated on the stack that has a destructor, this is the same as a declaration with the auto attribute. Although the current implementation does not put such objects on the stack, future ones can."
 One example I can think of that would
 break RAII is if the function gets inlined, then the stack allocated
 object may not be deleted until some point outside of the scope's end.
 It will /probably/ be deleted at the end of the function that the
 enclosing function was inlined into.  I could be wrong about that though.

I'm not sure what happens when something is inlined either.
 Also, does that C++ syntax allow class references to leak into code that
 is executed after the class is deleted?

I would expect not. They should be destroyed when the scope ends and the stack space is released.
  Now, take a Java/C# programmer, their first program with classes will  
 be:
  class A {
   int a;
 }
  void main() {
   A a = new A();
   writefln(a.a);
 }
  No crash, and the behaviour they expect.
  Then imagine the same programmers looking at each others code, the   
 C++ programmer will understand 'new' to indicate heap allocation and  
 the  Java/C# programmer will need to ask the C++ programmer what the  
 absense of  'new' means, he'll reply that the class is destroyed at the  
 end of scope.  He might also say it's stack allocated, but that's fine,  
 both of them have  something to learn, and it has no effect on the way  
 the program behaves.

That learning process would be nice, but it assumes an extra programmer being around. As I learn D, I am alone. Either I go to the spec or I ask on the newsgroup. I'm not sure how many others are in the same situation.

In the case where you're not looking at someone elses code you'll never write: A a = A(); so you will not learn about it until you go looking for RAII. There you'll find the syntax, learn it, and carry on. It's no harder to learn than a keyword 'local'.
 I've explained below why I still don't think it's very obvious, which
 means more potential newsgroup asking.  That doesn't bug me too much
 though.

I'm not especially bothered which syntax is chosen, I just like discussing stuff.
  Simple, intuitive and elegant no matter what your background. Of  
 course,  if you're a Java/C# programmer you have to 'learn' what the  
 absense of  'new' means. Both have to learn that D might not stack  
 allocate the RAII  class instance.
  If we use a 'scope' keyword then both sets of programmers have some   
 learning to do. It's not much worse, but this makes it my 2nd choice.

"Both have to learn that D might not stack allocate the RAII class instance." "If we use a 'scope' keyword then both sets of programmers have some learning to do." If they both have learning to do anyways, why not just have them learn 'scope'?

Right back at ya.. why not have them both learn to omit 'new'?
 I suppose it wouldn't be too bad otherwise, except for one problem:
 The unfortunate C++ programmer's program worked as expected.

Actually, my example was wrong and it doesn't. This poor guy still gets an access violation. Perhaps the new 'auto' syntax should just be: A a; then, my previous example and point would be valid.
 I say problem and unfortunate, because they may just assume that D
 behaves like C++ in all of the corner cases, and if I'm correct about
 the RAII vs stack alloc above, it may not.

One of the things Walter tends to do (which bothers some D users) is to emulate C/C++ where appropriate. This makes porting C/C++ to D easier because there aren't corner cases where it does something subtley different. Of course I may be wrong, there may be a corner case, but I believe Walter intentionally tries to reduce these. In our case, I believe the D syntax: auto A a = new A(); and the C++ syntax: A a; behave almost identically. The difference being that D current does not allocate on the stack, but, that may change and if it does they will behave identically.
 For a D newbie reading code, having a keyword is good because it  
 gives  them a keyword to search the spec for. Better yet if it is  
 'scope',  because that gives them an idea of where to look.  This is  
 also one of  those things that is used seldom enough that the  
 succinctness gained  from implicit things is only slightly helpful.

The Java/C++ programmer will search for 'new' (because it's absent). In either case they'll find the docs on RAII at the same time as they find the docs on 'new'.

Searching for 'new' is a good idea. What if they don't think of that?

Then they'll look for the section on variables, or class references, or declaring variables in function, or .. It shouldn't be all that hard to find, assuming half decent documentation.
 The only reason I would associate the absence of 'new' with allocation
 is because of the talk from C++ programmers on this newsgroup.
 Otherwise it's some kind of wacky cool feature of D that they have not
 read about yet (as it is now!).  This is why I prefer 'scope' - it would
 make scope, unambiguously, THE keyword to search for to find out what's
 going on.

Have you tried searching for an existing D keyword in the docs? First you have to decide which section to go to; is it a declaration, is it a type, is it a property, is it .. Sure it could be made easier with different documentation but that's all this boils down to, ensuring the information is in a logical place, if that's the case it makes no difference whether your searching for a specific keyword or 'RAII' or 'new' or 'class' etc. In an ideal world whatever you search for should find the results you need.
 In a nutshell: assume a programmer of undefined language background,  
 and  I believe 'scope' will be much more informative (and therefore   
 intuitive) than a blank space.

think removing 'new' is better than adding 'scope'.

That's fine as long as you clear up the two things: - What tells a non-C++ coder to look up 'new'? (besides another coder)

See above. This is a documentation issue.
 - The possible assumption by a C++ coder that RAII syntax means stack
 allocation.  (and subsequent whammy when they hit a pointy corner case)

 Proving that there are no corner cases in 'stack allocation implies
 RAII' or me being wrong about that meaning in C++ should clear up that
 second one.

See above. I believe the behaviour is almost identical (and may become identical in the future). I believe Walter intentionally avoids corner cases WRT C++ behavior. That's the best I can do.. if I knew of a corner case I'd let you know ;)
   What's the point of using static opCall here, as opposed to a  
 normal   static method or even a free function?

Why not a normal static method? - implementation hiding.

http://en.wikipedia.org/wiki/Information_hiding I'm not sure I follow your logic, did you mean "encapsulation" instead? If you did mean "information hiding" then it seems to me that using opCall is a design decision, just as using a method called "Bob" would be. The advantage to using "Bob" is that you can define an 'stable' interface eg. interface MyImplementation { int Bob(int x); } and in that way protect your code against changes in implementation. In short, this is a better "information hiding" solution than using static opCall.
 Why not a free function? - I'm assuming you mean a normal function   
 declared at module scope.

 It allows you to have multiple functions with access to the same   
 non-static variables (member variables).

_static_ opCall does *not* have access to non-static variables, it can only access static variables. Static methods and variables are very similar to module level variables. The difference being how to access them (class name prefix) and where they are declared (inside the class instead of at module level). You can replace static methods and variables with module level ones quite easily.
 I suppose this is usually accomplished with nested functions, or OOP   
 that can't do implementation hiding.

perhaps another example?
 Doing it this way allows me to avoid forward referencing issues

 and also gives me more options about how my code behaves.

 What problem does it solve?

Annoyance from forward referencing in nested functions, but that's just one. Maybe a small degree of implementation hiding for memory management, though I haven't tried this enough to demonstrate it. It is not really a solution. It is a technique, a syntax sugar, or just an easy way to get D to do things you would not ordinarily make it do.

- I'm not seeing the forward reference issue(s) - It seems like a worse way to implement information hiding (than an interface and method).
 What new technique or method does it allow?

Multiple functions using the same non-static variables with no need for forward referencing and possible code behaviour tweaks, etc yadda yadda. I admit it's not horribly important, but I don't think that this choice of syntax is either. Most of all, I like it.

static opCall seems to be fairly useless to me.
 *sigh* those were long winded answers, sorry about that.

not a bad thing.
 I do like using the scope keyword for this btw.  It seems quite    
 consistant with D's meaning of 'scope'.

It's not bad but it's my 2nd choice currently. Regan

Care to explain why static opCall is a hack and/or not useful outside of RAII or struct constructors?

of a place where _I_ would use it (which is why I think it's not useful). It's only a 'hack' when used with a struct to emulate a constructor. Strangely that 'hack' is the only vaguely good use I've seen for a *static* opCall. Regan

OK I think I have not explained my example very well. First I'll simplify my original example and try harder to explain. I've added comments this time. Here it is: import std.stdio; // class used as a function class f { int result; int tempVar1; // this is your non-static variable static int opCall( int x ) { // what do you know, not so 'static' after all! f instance = new f(x); int result = instance.result; // cleanup delete instance; return result; } this( int x ) { // If this were a function with nested functions, // then the main execution would occur here. result = x + internalFunc(); } // this is a non-static function int internalFunc() { return 314; } } void main() { int x = 42; x = f(x); writefln(x); } Now I'll rewrite it into a free function: import std.stdio; int f( int x ) { // Error! internalFunc is not defined. return x + internalFunc(); // oh but here it is... nested functions don't allow this int internalFunc() { return 314; } }

Err.. you've re-written your constructor as a free function? not the static opCall. Why? I would have expected this free function: int free_function( int x ) { // what do you know, not so 'static' after all! f instance = new f(x); int result = instance.result; // cleanup delete instance; return result; } void main() { int x = 42; x = free_function(x); writefln(x); } I've gotta go.. so, I'll just post what I've said so far and see what you respond with.. I may reply again to the stuff below.. :) Regan
 In a trivial case like this all you have to do is move the nested
 function internalFunc to the top.  In other cases though, where you want
 to be able to places the functions where they intuitively belong, this
 becomes annoying.  This is that forward referencing issue I was talking
 about.

 Also, if 'f' were derived from another class, then the code executed in  
 f's constructor would have access to the super class's members.  That's  
 more to do with OOP, but it's all hidden behind a static opCall.

 I suppose you could use a module function to construct and delete a  
 private class that gets used for it's own scope and inheritance.  I  
 worry that I am missing some detail that stopped me from just doing that  
 before.

 Sean, perhaps you could share some of your uses for static opCall since  
 I'm doing such a bad job at this?


 Only slightly related - I wonder if D's 'new' even implies heap  
 allocation as it is.  That might just be a dmd thing, but I am looking  
 in the spec at Classes -> ctors/dtors, and it doesn't say where they get  
 allocated.  Maybe someone who is good at searching the spec can find if  
 it says where classes get allocated?
 My thought, as xs0 has mentioned as well, is that 'new' could be defined  
 independant of those implementation details.  For example, just say that  
 'new' will allocate a class instance, and that the instance will be  
 cleaned up only after there are no more references to that class.  The  
 only exception being explicit deletion.  Since RAII gaurantees, AFAIK,  
 that there are no references leaked into code that gets executed after  
 the scope is exited, then stack allocation would work here.  I'm finding  
 it hard to imagine code that would require an object to be in the heap's  
 address range or in the stack's address range.  xs0 says there are other  
 cases in which a class can be allocated on the stack without breaking  
 the gaurantees of no premature deletion, and I wonder what they are.

Jul 28 2006
parent reply Chad J <gamerChad _spamIsBad_gmail.com> writes:
Regan Heath wrote:
 On Fri, 28 Jul 2006 04:44:44 -0400, Chad J  
 <gamerChad _spamIsBad_gmail.com> wrote:
 
 Regan Heath wrote:

  To expand on why I think it's intuitive let look at 2 scenarios, 
 first  the  C++ programmer trying D. Likely their first program 
 involving  classes will  look like this:
  class A {
   int a;
 }
  void main() {
   A a = A();
   writefln(a.a);
 }
  currently, this crashes with an access violation.

Actually, it doesn't compile. main.d(6): function expected before (), not A of type main.A main.d(6): cannot implicitly convert expression ((A)()) of type int to main.A Maybe not the best error messages for this case, but better than an access violation.

Err.. oops.. my example was in fact assuming the new "omit 'new'" syntax was added, then I went and confused it with: A a; writefln(a.a); which is actually what a C++ programmer would write to allocate a class on the stack and have it destroyed at end of scope. The syntax: A a; writefln(a.a); will crash, the new syntax isn't invloved at all, sorry.
 Add the new RAII syntax  and not only does it not crash, but it 
 behaves  just like a C++ program  would with A being destroyed at the 
 end of  scope.

I hear that such syntax, in C++, means that 'A' will be stack allocated, which AFAIK does not imply RAII.

No, but the resulting behaviour is almost identical. In C++ the syntax: A a; causes 'a' to be allocated on the stack and the destructor called at end of scope. Apart from being allocated on the stack (which Walter indicates in the docs is something he plans to implement at a later date for 'auto') it's identical to the behaviour of D's 'auto'. http://www.digitalmars.com/d/memory.html#stackclass "To have a class allocated on the stack that has a destructor, this is the same as a declaration with the auto attribute. Although the current implementation does not put such objects on the stack, future ones can."
 One example I can think of that would
 break RAII is if the function gets inlined, then the stack allocated
 object may not be deleted until some point outside of the scope's end.
 It will /probably/ be deleted at the end of the function that the
 enclosing function was inlined into.  I could be wrong about that though.

I'm not sure what happens when something is inlined either.
 Also, does that C++ syntax allow class references to leak into code that
 is executed after the class is deleted?

I would expect not. They should be destroyed when the scope ends and the stack space is released.
  Now, take a Java/C# programmer, their first program with classes 
 will  be:
  class A {
   int a;
 }
  void main() {
   A a = new A();
   writefln(a.a);
 }
  No crash, and the behaviour they expect.
  Then imagine the same programmers looking at each others code, the   
 C++ programmer will understand 'new' to indicate heap allocation and  
 the  Java/C# programmer will need to ask the C++ programmer what the  
 absense of  'new' means, he'll reply that the class is destroyed at 
 the  end of scope.  He might also say it's stack allocated, but 
 that's fine,  both of them have  something to learn, and it has no 
 effect on the way  the program behaves.

That learning process would be nice, but it assumes an extra programmer being around. As I learn D, I am alone. Either I go to the spec or I ask on the newsgroup. I'm not sure how many others are in the same situation.

In the case where you're not looking at someone elses code you'll never write: A a = A(); so you will not learn about it until you go looking for RAII. There you'll find the syntax, learn it, and carry on. It's no harder to learn than a keyword 'local'.

When reading other people's code, I find that most often I don't know or work with the other people. I'd have to contact them to learn from them. The easier option, for me, and probably them too, is to do a search in the spec, even if that is a bit difficult as-is.
 I've explained below why I still don't think it's very obvious, which
 means more potential newsgroup asking.  That doesn't bug me too much
 though.

I'm not especially bothered which syntax is chosen, I just like discussing stuff.
  Simple, intuitive and elegant no matter what your background. Of  
 course,  if you're a Java/C# programmer you have to 'learn' what the  
 absense of  'new' means. Both have to learn that D might not stack  
 allocate the RAII  class instance.
  If we use a 'scope' keyword then both sets of programmers have 
 some   learning to do. It's not much worse, but this makes it my 2nd 
 choice.

"Both have to learn that D might not stack allocate the RAII class instance." "If we use a 'scope' keyword then both sets of programmers have some learning to do." If they both have learning to do anyways, why not just have them learn 'scope'?

Right back at ya.. why not have them both learn to omit 'new'?

Point being it doesn't give you the win-lose, you're still stuck with a lose-lose. If both coders have to learn, then we lose the advantage of chosing this syntax to make it so C++ coders don't have to learn. You still have a point wrt similarity, though I dislike subtly different behaviours as it can lead to bad assumptions.
 I suppose it wouldn't be too bad otherwise, except for one problem:
 The unfortunate C++ programmer's program worked as expected.

Actually, my example was wrong and it doesn't. This poor guy still gets an access violation. Perhaps the new 'auto' syntax should just be: A a; then, my previous example and point would be valid.
 I say problem and unfortunate, because they may just assume that D
 behaves like C++ in all of the corner cases, and if I'm correct about
 the RAII vs stack alloc above, it may not.

One of the things Walter tends to do (which bothers some D users) is to emulate C/C++ where appropriate. This makes porting C/C++ to D easier because there aren't corner cases where it does something subtley different. Of course I may be wrong, there may be a corner case, but I believe Walter intentionally tries to reduce these. In our case, I believe the D syntax: auto A a = new A(); and the C++ syntax: A a; behave almost identically. The difference being that D current does not allocate on the stack, but, that may change and if it does they will behave identically.

OK I'd like some clarification about the C++ side of things. It seems to me that both syntaxes such as A a = A(); and A a; have been said to cause stack allocation in C++. Is this true? A a; Currently that is the syntax for declaring a variable. It will break any code that relies on 'a' being initialized to null. If that's alright, you could change it to mean RAII/stackalloc in the context of a function, but then you lose consistancy with D's practice of initializing variables to knownly invalid values.
 For a D newbie reading code, having a keyword is good because it  
 gives  them a keyword to search the spec for. Better yet if it is  
 'scope',  because that gives them an idea of where to look.  This 
 is  also one of  those things that is used seldom enough that the  
 succinctness gained  from implicit things is only slightly helpful.

The C++ programmer will already know what it does. The Java/C++ programmer will search for 'new' (because it's absent). In either case they'll find the docs on RAII at the same time as they find the docs on 'new'.

Searching for 'new' is a good idea. What if they don't think of that?

Then they'll look for the section on variables, or class references, or declaring variables in function, or .. It shouldn't be all that hard to find, assuming half decent documentation.
 The only reason I would associate the absence of 'new' with allocation
 is because of the talk from C++ programmers on this newsgroup.
 Otherwise it's some kind of wacky cool feature of D that they have not
 read about yet (as it is now!).  This is why I prefer 'scope' - it would
 make scope, unambiguously, THE keyword to search for to find out what's
 going on.

Have you tried searching for an existing D keyword in the docs? First you have to decide which section to go to; is it a declaration, is it a type, is it a property, is it .. Sure it could be made easier with different documentation but that's all this boils down to, ensuring the information is in a logical place, if that's the case it makes no difference whether your searching for a specific keyword or 'RAII' or 'new' or 'class' etc. In an ideal world whatever you search for should find the results you need.

Yeah. I find the current situation wrt searching the D spec pretty clumsy. It would really help to be able to search the spec, and just the spec, and not the forums or anything else at the same time. I think once that is handled, then using keywords searches will narrow things down to a very small number of results that someone could read through. Having to figure out what section something is in is good in some cases, but in others is a real drag IMO :(
 In a nutshell: assume a programmer of undefined language 
 background,  and  I believe 'scope' will be much more informative 
 (and therefore   intuitive) than a blank space.

I've assumed programmers from 2 types of background above, I still think removing 'new' is better than adding 'scope'.

That's fine as long as you clear up the two things: - What tells a non-C++ coder to look up 'new'? (besides another coder)

See above. This is a documentation issue.
 - The possible assumption by a C++ coder that RAII syntax means stack
 allocation.  (and subsequent whammy when they hit a pointy corner case)

 Proving that there are no corner cases in 'stack allocation implies
 RAII' or me being wrong about that meaning in C++ should clear up that
 second one.

See above. I believe the behaviour is almost identical (and may become identical in the future). I believe Walter intentionally avoids corner cases WRT C++ behavior. That's the best I can do.. if I knew of a corner case I'd let you know ;)
 OK I think I have not explained my example very well.
 First I'll simplify my original example and try harder to explain.  I've
 added comments this time.
 Here it is:

 import std.stdio;

 // class used as a function
 class f
 {
      int result;
      int tempVar1; // this is your non-static variable

      static int opCall( int x )
      {
          // what do you know, not so 'static' after all!
          f instance = new f(x);
          int result = instance.result;

          // cleanup
          delete instance;
          return result;
      }

      this( int x )
      {
          // If this were a function with nested functions,
          //   then the main execution would occur here.
          result = x + internalFunc();
      }

      // this is a non-static function
      int internalFunc()
      {
          return 314;
      }
 }

 void main()
 {
      int x = 42;
      x = f(x);
      writefln(x);
 }

 Now I'll rewrite it into a free function:

 import std.stdio;

 int f( int x )
 {
       // Error! internalFunc is not defined.
      return x + internalFunc();

      // oh but here it is... nested functions don't allow this
      int internalFunc()
      {
          return 314;
      }
 }

Err.. you've re-written your constructor as a free function? not the static opCall. Why? I would have expected this free function: int free_function( int x ) { // what do you know, not so 'static' after all! f instance = new f(x); int result = instance.result; // cleanup delete instance; return result; } void main() { int x = 42; x = free_function(x); writefln(x); }

That does work. Forces you to put the function outside of the class, but meh, it's just aesthetics/syntax sugar.
 I've gotta go.. so, I'll just post what I've said so far and see what 
 you  respond with.. I may reply again to the stuff below.. :)
 
 Regan
 
 In a trivial case like this all you have to do is move the nested
 function internalFunc to the top.  In other cases though, where you want
 to be able to places the functions where they intuitively belong, this
 becomes annoying.  This is that forward referencing issue I was talking
 about.

 Also, if 'f' were derived from another class, then the code executed 
 in  f's constructor would have access to the super class's members.  
 That's  more to do with OOP, but it's all hidden behind a static opCall.

 I suppose you could use a module function to construct and delete a  
 private class that gets used for it's own scope and inheritance.  I  
 worry that I am missing some detail that stopped me from just doing 
 that  before.

 Sean, perhaps you could share some of your uses for static opCall 
 since  I'm doing such a bad job at this?


 Only slightly related - I wonder if D's 'new' even implies heap  
 allocation as it is.  That might just be a dmd thing, but I am 
 looking  in the spec at Classes -> ctors/dtors, and it doesn't say 
 where they get  allocated.  Maybe someone who is good at searching the 
 spec can find if  it says where classes get allocated?
 My thought, as xs0 has mentioned as well, is that 'new' could be 
 defined  independant of those implementation details.  For example, 
 just say that  'new' will allocate a class instance, and that the 
 instance will be  cleaned up only after there are no more references 
 to that class.  The  only exception being explicit deletion.  Since 
 RAII gaurantees, AFAIK,  that there are no references leaked into code 
 that gets executed after  the scope is exited, then stack allocation 
 would work here.  I'm finding  it hard to imagine code that would 
 require an object to be in the heap's  address range or in the stack's 
 address range.  xs0 says there are other  cases in which a class can 
 be allocated on the stack without breaking  the gaurantees of no 
 premature deletion, and I wonder what they are.


Aug 02 2006
parent "Regan Heath" <regan netwin.co.nz> writes:
 If they both have learning to do anyways, why not just have them learn
 'scope'?


Point being it doesn't give you the win-lose, you're still stuck with a lose-lose. If both coders have to learn, then we lose the advantage of chosing this syntax to make it so C++ coders don't have to learn.

True.. however not being a C++ programmer "on a daily basis" I can't say for certain which of the 2 syntaxes I have given as examples of how a C++ programmer would do it, is the more common.
 You still have a point wrt similarity, though I dislike subtly different  
 behaviours as it can lead to bad assumptions.

Different behaviour (heap vs stack allocation) is only a problem if it changes the outcome of the program. heap vs stack doesn't change the outcome, but it might affect the speed/efficiency of the program as doing 1,000,000 heap allocations is slower than the same number of stack ones. Adding stack allocation to 'auto' would then be a speed optimisation.
  In our case, I believe the D syntax:
  auto A a = new A();
  and the C++ syntax:
  A a;
  behave almost identically. The difference being that D current does  
 not  allocate on the stack, but, that may change and if it does they  
 will  behave identically.

OK I'd like some clarification about the C++ side of things. It seems to me that both syntaxes such as A a = A(); and A a; have been said to cause stack allocation in C++. Is this true?

Yes, I believe so. To heap allocate you have to use 'new'. My MSDN docs say.. "The new operator is used to allocate objects and arrays of objects. The new operator allocates from a program memory area called the “free store.” In C, the free store is often referred to as the “heap.”"
 A a;
 Currently that is the syntax for declaring a variable.

D initialises 'a' to null.
 It will break any code that relies on 'a' being initialized to null.

No. But it will break any code which assumes it's not null, which is what the poor C++ programmer discovers in his/her first D program.
 If that's alright, you could change it to mean RAII/stackalloc in the  
 context of a function, but then you lose consistancy with D's practice  
 of initializing variables to knownly invalid values.

True. A a; would have to call the class constructor, so it would have a known 'valid' value instead. Likewise:' A a = A(1,2,3); would do the same, only this time you can pass parameters to the class constructor. These two syntaxes are really one and the same.
 That does work.  Forces you to put the function outside of the class,  
 but meh, it's just aesthetics/syntax sugar.

"function outside of the class" is what I meant by "free function" .. he's free, not trapped in a class ;) So.. I'm still left with little idea when someone would actually use a static opCall and what purpose/problem it solves (beyond being syntactic sugar for free functions or other static methods of a class). If it's just syntactic sugar _and_ we decide we like the omit 'new' syntax (doesn't look promising at this stage, no matter) then I would vote for static opCall to be removed. Regan
Aug 02 2006
prev sibling parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Chad J wrote:
 Regan Heath wrote:
 
 Add the new RAII syntax  and not only does it not crash, but it 
 behaves just like a C++ program  would with A being destroyed at the 
 end of scope.

I hear that such syntax, in C++, means that 'A' will be stack allocated, which AFAIK does not imply RAII. One example I can think of that would break RAII is if the function gets inlined, then the stack allocated object may not be deleted until some point outside of the scope's end. It will /probably/ be deleted at the end of the function that the enclosing function was inlined into. I could be wrong about that though.

Uh, scopes and stack "frames" do not exist only for function frames. They exist for any instruction-block/scope. Such that: void func() { auto Foo fooa = new Foo; { auto Foo foob = new Foo; } // foob gets destroyed here ... } // fooa gets destroyed here So similarly, function inlining creates a scope/instruction-block , so that allocation behavior is preserved. So this code: int a = 2, b = 3; int r = sum(a, b); gets inlined to this: int a = 2, b = 3; int r; { r = a + b; } // De-alloc autos if there were any. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 29 2006
parent Chad J <gamerChad _spamIsBad_gmail.com> writes:
Bruno Medeiros wrote:
 Chad J wrote:
 
 Regan Heath wrote:

 Add the new RAII syntax  and not only does it not crash, but it 
 behaves just like a C++ program  would with A being destroyed at the 
 end of scope.

I hear that such syntax, in C++, means that 'A' will be stack allocated, which AFAIK does not imply RAII. One example I can think of that would break RAII is if the function gets inlined, then the stack allocated object may not be deleted until some point outside of the scope's end. It will /probably/ be deleted at the end of the function that the enclosing function was inlined into. I could be wrong about that though.

Uh, scopes and stack "frames" do not exist only for function frames. They exist for any instruction-block/scope. Such that: void func() { auto Foo fooa = new Foo; { auto Foo foob = new Foo; } // foob gets destroyed here ... } // fooa gets destroyed here So similarly, function inlining creates a scope/instruction-block , so that allocation behavior is preserved. So this code: int a = 2, b = 3; int r = sum(a, b); gets inlined to this: int a = 2, b = 3; int r; { r = a + b; } // De-alloc autos if there were any.

Ah. Thanks for the info.
Aug 02 2006
prev sibling parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Regan Heath wrote:
 On Tue, 25 Jul 2006 23:28:24 -0400, Chad J 
 I really don't like the idea of dropping a language feature just for 
 the sake of having a particular syntax that, IMO, is not intuitive.

It's the same syntax you see in C++ for a class that has it's destructor called at the end of the scope. That, to me, makes it intuitive. For what reason do you find it un-intuitive?

Are you saying it is intuitive because *it is the same syntax as C++* ?? I hope not, because being the same syntax as C++ not only does not make it intuitive, but it also likely has the inverse effect: making things un-intuitive. -- Bruno Medeiros - MSc. in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 29 2006
parent "Regan Heath" <regan netwin.co.nz> writes:
On Sat, 29 Jul 2006 21:20:22 +0100, Bruno Medeiros  
<brunodomedeirosATgmail SPAM.com> wrote:
 Regan Heath wrote:
 On Tue, 25 Jul 2006 23:28:24 -0400, Chad J
 I really don't like the idea of dropping a language feature just for  
 the sake of having a particular syntax that, IMO, is not intuitive.

destructor called at the end of the scope. That, to me, makes it intuitive. For what reason do you find it un-intuitive?

Are you saying it is intuitive because *it is the same syntax as C++* ?? I hope not, because being the same syntax as C++ not only does not make it intuitive, but it also likely has the inverse effect: making things un-intuitive.

I was in fact wrong about the syntax being the same. That said, syntax and behaviour which is similar to C++ is intuitive (to C++ programmers). That's all I sugested (you need to read my statement in context with the example of the C++ and Java/C# programmers). I was attempting to compare the 2 proposals: - absence of 'new' - use of keyword 'scope' or 'local' or <insert favourite keyword> by describing how a programmer from either the C++ or Java/C# world might encounter the RAII syntax, as far as I can see they'll either: 1. read some code using it. 2. want to implement RAII and will search the docs. I don't think either method is significantly better or worse in these 2 situations regardless of the programmers background. My mistake was that I thought the "absence of new" syntax was the same as the C++ syntax (for stack allocated, destroy at end of scope classes). This would have made it 'more' intuitive to the general population by virtue of being 'more' intuitive to the C++ programmers. In fact, if the suggested RAII syntax was: class A {} A a; //allocate RAII class then the C++ programmer, who wrote the above for his/her first D program wouldn't get an access violation (as they currently do) and would instead get the expected behaviour. An object (not allocated on the stack.. yet) whose destructor is called at end of scope. So, perhaps the RAII syntax should be this? It benefits C++ programmers and does not hurt Java/C# programmer any more than having to learn and use a new keyword (as it's essentially the same thing) Regan
Jul 31 2006
prev sibling next sibling parent reply xs0 <xs0 xs0.com> writes:
 I say lets keep 'auto' for auto type inference (for the reasons you and 
 Don mention)

agreed.
 I like the use of scope at class decl. But, I prefer the no keyword 
 approach at instantiation. So, allow me to suggest this as a 3rd option.
 
 - 'scope' at class decl.
 - no keyword at instatiation.
 
 Reasoning:
 
 'new' implies heap allocation to me. It would be beneficial to allow the 
 compiler to allocate an RAII type in any way it wants, perhaps stack 
 allocating it. Removing 'new' removes the implied heap allocation 
 allowing the compiler to allocate however it likes.

Why would you want to deal with where the object is allocated? Besides speed, is there any reason at all to allocate on the stack? If you always type the same thing, the compiler is always free to choose the best location. If you restrict "new" to allocating on the heap, you prevent the compiler from optimizing (by allocating on the stack) whenever it determines it's safe to do so (scoped variables are not the only such case). Imho, "scope" is a perfect keyword for scoped variables/classes, for reasons already stated (already exists, good meaning, explicit). A missing "new" is not a good keyword ;) By the way, I think it would be wise to require references to scope-classes also be tagged with scope, so it'd be harder to miss that not-so-insignificant detail about them..
 I don't see the utility in static opCall, I say abolish/remove it. 
 Non-static opCall on the other hand can be quite useful.

But there is utility in static opCall in structs; having them there but not in classes doesn't sound to cool/consistent.. xs0
Jul 26 2006
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 26 Jul 2006 11:58:31 +0200, xs0 <xs0 xs0.com> wrote:
 I say lets keep 'auto' for auto type inference (for the reasons you and  
 Don mention)

agreed.
 I like the use of scope at class decl. But, I prefer the no keyword  
 approach at instantiation. So, allow me to suggest this as a 3rd option.
  - 'scope' at class decl.
 - no keyword at instatiation.
  Reasoning:
  'new' implies heap allocation to me. It would be beneficial to allow  
 the compiler to allocate an RAII type in any way it wants, perhaps  
 stack allocating it. Removing 'new' removes the implied heap allocation  
 allowing the compiler to allocate however it likes.

Why would you want to deal with where the object is allocated?

My post _must_ have been missleading (more than one person thinks I want stack allocation). I don't want stack allocation. I was simply raising the possibility of stack allocation as a possibly beneficial side-effect of removing 'new' (which implies/required heap allocation, AFAICS)
 Besides speed, is there any reason at all to allocate on the stack?

Speed isn't a good enough reason?
 If you always type the same thing, the compiler is always free to choose  
 the best location. If you restrict "new" to allocating on the heap, you  
 prevent the compiler from optimizing (by allocating on the stack)  
 whenever it determines it's safe to do so (scoped variables are not the  
 only such case).

Is it even possible for 'new' to allocate on the stack? I mean the stack vanishes when the function exits, therefore isn't 'new' restricted to the heap?
 Imho, "scope" is a perfect keyword for scoped variables/classes, for  
 reasons already stated (already exists, good meaning, explicit). A  
 missing "new" is not a good keyword ;)

I disagree, see my recent reply to "Chad J", specifically the scenarios involving the C++ and Java programmers.
 I don't see the utility in static opCall, I say abolish/remove it.  
 Non-static opCall on the other hand can be quite useful.

But there is utility in static opCall in structs; having them there but not in classes doesn't sound to cool/consistent..

The only utility in static opCall is to emulate a constructor. Why not replace them with a constructor (ie. rename "static opCall" to "this"). Then, remove static opCall altogether. Regan
Jul 26 2006
next sibling parent reply Tommie Gannert <tomime gannert.se> writes:
 I don't see the utility in static opCall, I say abolish/remove it. 
 Non-static opCall on the other hand can be quite useful.

But there is utility in static opCall in structs; having them there but not in classes doesn't sound to cool/consistent..

The only utility in static opCall is to emulate a constructor. Why not replace them with a constructor (ie. rename "static opCall" to "this"). Then, remove static opCall altogether.

I haven't been following this, but static opCall sounds an awful lot like a function call to a function with static variables... I must join the "who would want such a thing"-side. /T
Jul 26 2006
parent Sean Kelly <sean f4.ca> writes:
Tommie Gannert wrote:
 I don't see the utility in static opCall, I say abolish/remove it. 
 Non-static opCall on the other hand can be quite useful.

But there is utility in static opCall in structs; having them there but not in classes doesn't sound to cool/consistent..

The only utility in static opCall is to emulate a constructor. Why not replace them with a constructor (ie. rename "static opCall" to "this"). Then, remove static opCall altogether.

I haven't been following this, but static opCall sounds an awful lot like a function call to a function with static variables... I must join the "who would want such a thing"-side.

Support for static operator functions can be useful for refactoring code in some cases, or for some odd template uses. I don't use the feature very often, but it's nice to have available. Sean
Jul 27 2006
prev sibling parent reply xs0 <xs0 xs0.com> writes:
Regan Heath wrote:
 On Wed, 26 Jul 2006 11:58:31 +0200, xs0 <xs0 xs0.com> wrote:
 I like the use of scope at class decl. But, I prefer the no keyword 
 approach at instantiation. So, allow me to suggest this as a 3rd option.
  - 'scope' at class decl.
 - no keyword at instatiation.
  Reasoning:
  'new' implies heap allocation to me. It would be beneficial to allow 
 the compiler to allocate an RAII type in any way it wants, perhaps 
 stack allocating it. Removing 'new' removes the implied heap 
 allocation allowing the compiler to allocate however it likes.

Why would you want to deal with where the object is allocated?

My post _must_ have been missleading (more than one person thinks I want stack allocation). I don't want stack allocation. I was simply raising the possibility of stack allocation as a possibly beneficial side-effect of removing 'new' (which implies/required heap allocation, AFAICS)

'new' doesn't imply/require that heap allocation actually be done, it just requires the result to behave as if it was (look up "escape analysis")
 Besides speed, is there any reason at all to allocate on the stack?

Speed isn't a good enough reason?

Speed is a good reason to use stack allocation. But that is also a good reason to let the compiler determine where to place an object, not the programmer.
 If you always type the same thing, the compiler is always free to 
 choose the best location. If you restrict "new" to allocating on the 
 heap, you prevent the compiler from optimizing (by allocating on the 
 stack) whenever it determines it's safe to do so (scoped variables are 
 not the only such case).

Is it even possible for 'new' to allocate on the stack? I mean the stack vanishes when the function exits, therefore isn't 'new' restricted to the heap?

No. There are many cases where the object is not actually required to be on the heap.
 Imho, "scope" is a perfect keyword for scoped variables/classes, for 
 reasons already stated (already exists, good meaning, explicit). A 
 missing "new" is not a good keyword ;)

I disagree, see my recent reply to "Chad J", specifically the scenarios involving the C++ and Java programmers.

Well, I'm a Java programmer and if I see A a = A(); I see a function call that returns something of type A. If I see auto a = A(); I definitely see a function call. You'll never convince me that the lack of "new" is a good indication of anything, much less of the fact that it's a scoped variable.
 The only utility in static opCall is to emulate a constructor. Why not 
 replace them with a constructor (ie. rename "static opCall" to "this"). 
 Then, remove static opCall altogether.

Emulating a constructor is not the only utility, it's emulating an arbitrary function. xs0
Jul 27 2006
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 27 Jul 2006 15:31:24 +0200, xs0 <xs0 xs0.com> wrote:
 Regan Heath wrote:
 On Wed, 26 Jul 2006 11:58:31 +0200, xs0 <xs0 xs0.com> wrote:
 I like the use of scope at class decl. But, I prefer the no keyword  
 approach at instantiation. So, allow me to suggest this as a 3rd  
 option.
  - 'scope' at class decl.
 - no keyword at instatiation.
  Reasoning:
  'new' implies heap allocation to me. It would be beneficial to allow  
 the compiler to allocate an RAII type in any way it wants, perhaps  
 stack allocating it. Removing 'new' removes the implied heap  
 allocation allowing the compiler to allocate however it likes.

Why would you want to deal with where the object is allocated?

want stack allocation). I don't want stack allocation. I was simply raising the possibility of stack allocation as a possibly beneficial side-effect of removing 'new' (which implies/required heap allocation, AFAICS)

'new' doesn't imply/require that heap allocation actually be done, it just requires the result to behave as if it was (look up "escape analysis")

Ok.
 Besides speed, is there any reason at all to allocate on the stack?


Speed is a good reason to use stack allocation. But that is also a good reason to let the compiler determine where to place an object, not the programmer.

Exactly. I never suggested otherwise :)
 If you always type the same thing, the compiler is always free to  
 choose the best location. If you restrict "new" to allocating on the  
 heap, you prevent the compiler from optimizing (by allocating on the  
 stack) whenever it determines it's safe to do so (scoped variables are  
 not the only such case).

stack vanishes when the function exits, therefore isn't 'new' restricted to the heap?

No. There are many cases where the object is not actually required to be on the heap.

Example?
 Imho, "scope" is a perfect keyword for scoped variables/classes, for  
 reasons already stated (already exists, good meaning, explicit). A  
 missing "new" is not a good keyword ;)

scenarios involving the C++ and Java programmers.

Well, I'm a Java programmer and if I see A a = A(); I see a function call that returns something of type A. If I see auto a = A(); I definitely see a function call. You'll never convince me that the lack of "new" is a good indication of anything, much less of the fact that it's a scoped variable.

Have you read my other post? Are you telling me you have a "closed mind"? If so, this discussion is pointless.
 The only utility in static opCall is to emulate a constructor. Why not  
 replace them with a constructor (ie. rename "static opCall" to "this").  
 Then, remove static opCall altogether.

Emulating a constructor is not the only utility, it's emulating an arbitrary function.

Yes, but it's a 'static' function. See my other post WRT "information hiding", for that purpose it's actually better to use an actual static function. Regan
Jul 27 2006
parent reply xs0 <xs0 xs0.com> writes:
Regan Heath wrote:

 'new' doesn't imply/require that heap allocation actually be done, it 
 just requires the result to behave as if it was (look up "escape 
 analysis")

Ok.
 Besides speed, is there any reason at all to allocate on the stack?


Speed is a good reason to use stack allocation. But that is also a good reason to let the compiler determine where to place an object, not the programmer.

Exactly. I never suggested otherwise :)

You did - you propose that using "new" forces the allocation on the heap, while not using it leaves the choice to the compiler (however, the variable is then also scoped/raii/auto/banana, so there's not much choice anyway).
  Is it even possible for 'new' to allocate on the stack? I mean the 
 stack vanishes when the function exits, therefore isn't 'new' 
 restricted to the heap?

No. There are many cases where the object is not actually required to be on the heap.

Example?

Did you look up escape analysis like I suggested? Anyway, besides the obvious scoped/raii/auto/banana variables, here's a simple example: void foo(Object a) { writefln("%s", a.toString()); } main() { foo(new Whatever()); } There's no reason why Whatever would have to be on the heap.
 Imho, "scope" is a perfect keyword for scoped variables/classes, for 
 reasons already stated (already exists, good meaning, explicit). A 
 missing "new" is not a good keyword ;)

scenarios involving the C++ and Java programmers.

Well, I'm a Java programmer and if I see A a = A(); I see a function call that returns something of type A. If I see auto a = A(); I definitely see a function call. You'll never convince me that the lack of "new" is a good indication of anything, much less of the fact that it's a scoped variable.

Have you read my other post? Are you telling me you have a "closed mind"? If so, this discussion is pointless.

Dude, what's wrong with you? Your argument was that Java programmers would see an allocating expression without "new" or any other keyword, and somehow magically determine that there's something to be learned. I responded by saying that they (or me) wouldn't even see it as an allocating expression, and for that I have a closed mind? You know, you're probably right, this discussion is pointless, like so many others you participate in. And I still don't get how you can even think that "" can be a better indication of anything than "scope" (or any other keyword). When you see an empty paper, does a thought "oooh, I need to learn about D's scoped variables" spring to your mind?
 The only utility in static opCall is to emulate a constructor. Why 
 not replace them with a constructor (ie. rename "static opCall" to 
 "this"). Then, remove static opCall altogether.

Emulating a constructor is not the only utility, it's emulating an arbitrary function.

Yes, but it's a 'static' function. See my other post WRT "information hiding", for that purpose it's actually better to use an actual static function.

Without even reading your other post, I never said it's always better to use static opCall. I'm just saying there are cases where it's cool to have. But, this is basically a separate discussion anyway, so no need to continue with it. xs0
Jul 28 2006
parent "Regan Heath" <regan netwin.co.nz> writes:
On Fri, 28 Jul 2006 12:12:49 +0200, xs0 <xs0 xs0.com> wrote:
 Regan Heath wrote:

 'new' doesn't imply/require that heap allocation actually be done, it  
 just requires the result to behave as if it was (look up "escape  
 analysis")

 Besides speed, is there any reason at all to allocate on the stack?


Speed is a good reason to use stack allocation. But that is also a good reason to let the compiler determine where to place an object, not the programmer.


You did - you propose that using "new" forces the allocation on the heap, while not using it leaves the choice to the compiler (however, the variable is then also scoped/raii/auto/banana, so there's not much choice anyway).

I'm arguing semantics perhaps but all I did was say that it 'implied' heap allocation 'in my opinion'. My exact words were..
 Quoting "Regan Heath"..
 'new' implies heap allocation to me. It would be beneficial to allow the 
 compiler to allocate an RAII type in any way it wants, perhaps stack
 allocating it. Removing 'new' removes the implied heap allocation 
 allowing the compiler to allocate however it likes.


Until you gave the example below (thanks for that) I did suspect that it was required for 'new' to heap allocate because stack allocation only 'lives' as long as the scope in which it's allocated. So, stack allocation could be done for 'new' in certain cases (like the example below) to optimise, cool. To me 'new' still 'implies' heap allocation. But, now I know that there are some situations where the compiler could stack allocate, situations where the object allocated by 'new' only 'lives' as long as the current scope.
  Is it even possible for 'new' to allocate on the stack? I mean the  
 stack vanishes when the function exits, therefore isn't 'new'  
 restricted to the heap?

No. There are many cases where the object is not actually required to be on the heap.


Did you look up escape analysis like I suggested?

Yes. But I still wanted an example from you :)
 Anyway, besides the obvious scoped/raii/auto/banana variables, here's a  
 simple example:

 void foo(Object a)
 {
      writefln("%s", a.toString());
 }

 main()
 {
      foo(new Whatever());
 }

 There's no reason why Whatever would have to be on the heap.

Nice. So an optimising compiler may choose to allocate 'a' on the stack. It can do that because the object only 'lives' as long as the scope of the function 'foo', correct?
 Imho, "scope" is a perfect keyword for scoped variables/classes, for  
 reasons already stated (already exists, good meaning, explicit). A  
 missing "new" is not a good keyword ;)

scenarios involving the C++ and Java programmers.

Well, I'm a Java programmer and if I see A a = A(); I see a function call that returns something of type A. If I see auto a = A(); I definitely see a function call. You'll never convince me that the lack of "new" is a good indication of anything, much less of the fact that it's a scoped variable.

Are you telling me you have a "closed mind"? If so, this discussion is pointless.

Dude, what's wrong with you? Your argument was that Java programmers would see an allocating expression without "new" or any other keyword, and somehow magically determine that there's something to be learned. I responded by saying that they (or me) wouldn't even see it as an allocating expression, and for that I have a closed mind?

Your comment "You'll never convince me.. " caused my response wrt "closed mind". I meant no offence by it.
 You know, you're probably right, this discussion is pointless, like so  
 many others you participate in.

You seem to be atributing me with some sort of malice towards you, that's simply not the case. I avoid posting anything while I'm angry as I tend to regret it. I wasn't even angry or annoyed in this case, just curious. I seem to have angered you, I apologise for that.
 And I still don't get how you can even think that "" can be a better  
 indication of anything than "scope" (or any other keyword).

Then I'm doing a bad job of explaining. I believe you've missunderstood some of what I've tried to say (also my fault for choosing the wrong words to explain it)
 The only utility in static opCall is to emulate a constructor. Why  
 not replace them with a constructor (ie. rename "static opCall" to  
 "this"). Then, remove static opCall altogether.

Emulating a constructor is not the only utility, it's emulating an arbitrary function.

hiding", for that purpose it's actually better to use an actual static function.

Without even reading your other post, I never said it's always better to use static opCall. I'm just saying there are cases where it's cool to have. But, this is basically a separate discussion anyway, so no need to continue with it.

Actually I think it's important to this discussion. If static opCall is truly useful it makes the 'absence of new' idea rather worse than using a keyword. Among other things I'm trying to determine when/where static opCall is used, and why it's used in favour of another method (or even if one such method exists). I also wanted to know when 'new' could do something other than heap allocate, you've answered that one, thanks. Regan
Jul 31 2006
prev sibling parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Regan Heath wrote:
 On Tue, 25 Jul 2006 10:17:13 -0700, kris <foo bar.com> wrote:
 Don has a good point: changing to "var" would cause conflict with 
 existing variable-names.

 Chad et. al. also have a good point about the conflict regarding 
 static opCall() (via the lack of a "new" keyword). I suspect many 
 people find the use of "new" to be indicative of allocation, and 
 breaking this consistency may have a detrimental effect? Further, it 
 was noted that a missing "new" can only be used at the instantiation 
 site -- not at the class decl -- thus, D would be losing an existing 
 feature.

 I suspect you could count the current number of raii-class uses on a 
 few hands, whereas the use of "auto" for implied-type is pretty darned 
 popular -- and rightly so, since it's really very, very useful. 
 Changing the raii style to use a different keyword, whilst retaining 
 implied-type "auto" would be an almost imperceptible change?

 Thus, it would appear to make sense to retain "auto" for implied-type, 
 and introduce something *else* for automatic cleanup at end-of-scope 
 (and also as a class attribute). how about reusing the "scope" keyword?

 void main()
 {
    auto i = 10;
    auto foo = new Foo;
    auto scope bar = new Bar;
    auto scope wumpus = new Wumpus;
 }

 class Foo {}

 class Bar {}

 scope class Wumpus {}

I say lets keep 'auto' for auto type inference (for the reasons you and Don mention) I like the use of scope at class decl. But, I prefer the no keyword approach at instantiation. So, allow me to suggest this as a 3rd option. - 'scope' at class decl. - no keyword at instatiation. Reasoning: 'new' implies heap allocation to me. It would be beneficial to allow the compiler to allocate an RAII type in any way it wants, perhaps stack allocating it. Removing 'new' removes the implied heap allocation allowing the compiler to allocate however it likes. I don't see the utility in static opCall, I say abolish/remove it. Non-static opCall on the other hand can be quite useful. Regan

I don't like the no-allocator-keyword proposal. There are the problems: * the lack of static opCall (which I don't have experience with, so I'll leave the arguing about the usefulness of it to others). * less clear in the code that an allocation (stack or otherwise) is taking place. (somewhat subjective/aesthetical point I guess) But most importantly: * You can't make auto objects out of objects allocated with a function (like a factory method) instead of inline allocation. For example, the following cannot be made with a no-allocator-keyword syntax: auto Foo foo = SomeFactory.newFoo(..); // can't make an auto here auto char[] a = read(filename); // can't make an auto here -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 29 2006
parent "Regan Heath" <regan netwin.co.nz> writes:
On Sat, 29 Jul 2006 22:17:07 +0100, Bruno Medeiros  
<brunodomedeirosATgmail SPAM.com> wrote:
 But most importantly:
 * You can't make auto objects out of objects allocated with a function
 (like a factory method) instead of inline allocation. For example, the
 following cannot be made with a no-allocator-keyword syntax:
    auto Foo foo = SomeFactory.newFoo(..); // can't make an auto here
    auto char[] a = read(filename); // can't make an auto here

Good point. That's a big problem. Regan
Jul 31 2006
prev sibling next sibling parent reply "Chris Miller" <chris dprogramming.com> writes:
I vote for banana!

or scope.. seems good to reuse it; without parentheses after scope keywo=
rd  =

implying `end of scope destruction`.


On Tue, 25 Jul 2006 13:17:13 -0400, kris <foo bar.com> wrote:

 Don has a good point: changing to "var" would cause conflict with  =

 existing variable-names.

 Chad et. al. also have a good point about the conflict regarding stati=

 opCall() (via the lack of a "new" keyword). I suspect many people find=

 the use of "new" to be indicative of allocation, and breaking this  =

 consistency may have a detrimental effect? Further, it was noted that =

 missing "new" can only be used at the instantiation site -- not at the=

 class decl -- thus, D would be losing an existing feature.

 I suspect you could count the current number of raii-class uses on a f=

 hands, whereas the use of "auto" for implied-type is pretty darned  =

 popular -- and rightly so, since it's really very, very useful. Changi=

 the raii style to use a different keyword, whilst retaining implied-ty=

 "auto" would be an almost imperceptible change?

 Thus, it would appear to make sense to retain "auto" for implied-type,=

 and introduce something *else* for automatic cleanup at end-of-scope  =

 (and also as a class attribute). how about reusing the "scope" keyword=

 void main()
 {
    auto i =3D 10;
    auto foo =3D new Foo;
    auto scope bar =3D new Bar;
    auto scope wumpus =3D new Wumpus;
 }

 class Foo {}

 class Bar {}

 scope class Wumpus {}

Jul 25 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Chris Miller" <chris dprogramming.com> wrote in message 
news:op.tc91g1fjpo9bzi moe...
 I vote for banana!

banana++
 or scope.. seems good to reuse it; without parentheses after scope keyword 
 implying `end of scope destruction`.

I like scope for RAII too. Wonder who originally suggested that *cough*cough* ;)
Jul 27 2006
parent Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Jarrett Billingsley wrote:
 "Chris Miller" <chris dprogramming.com> wrote in message 
 news:op.tc91g1fjpo9bzi moe...
 I vote for banana!

banana++

No!! I often use banana as an identifier in many of my programs! :P -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 29 2006
prev sibling next sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
vote++;
//me likes

kris wrote:
 Don has a good point: changing to "var" would cause conflict with 
 existing variable-names.
 
 Chad et. al. also have a good point about the conflict regarding static 
 opCall() (via the lack of a "new" keyword). I suspect many people find 
 the use of "new" to be indicative of allocation, and breaking this 
 consistency may have a detrimental effect? Further, it was noted that a 
 missing "new" can only be used at the instantiation site -- not at the 
 class decl -- thus, D would be losing an existing feature.
 
 I suspect you could count the current number of raii-class uses on a few 
 hands, whereas the use of "auto" for implied-type is pretty darned 
 popular -- and rightly so, since it's really very, very useful. Changing 
 the raii style to use a different keyword, whilst retaining implied-type 
 "auto" would be an almost imperceptible change?
 
 Thus, it would appear to make sense to retain "auto" for implied-type, 
 and introduce something *else* for automatic cleanup at end-of-scope 
 (and also as a class attribute). how about reusing the "scope" keyword?
 
 void main()
 {
   auto i = 10;
   auto foo = new Foo;
   auto scope bar = new Bar;
   auto scope wumpus = new Wumpus;
 }
 
 class Foo {}
 
 class Bar {}
 
 scope class Wumpus {}
 
 
 
 
 
 

Jul 26 2006
parent reply "John Reimer" <terminal.node gmail.com> writes:
On Wed, 26 Jul 2006 02:52:06 -0700, Hasan Aljudy <hasan.aljudy gmail.com>  
wrote:

 vote++;
 //me likes

I am sympathetic to the "scope" suggestion also. People have to remember that Walter doesn't like adding any new keywords. Reuse of "scope" may be the best solution here. Are there any drawbacks? Does it fit the intended meaning and purpose appropriately? It seems to. -JJR
Jul 27 2006
parent reply Sean Kelly <sean f4.ca> writes:
John Reimer wrote:
 On Wed, 26 Jul 2006 02:52:06 -0700, Hasan Aljudy 
 <hasan.aljudy gmail.com> wrote:
 
 vote++;
 //me likes

I am sympathetic to the "scope" suggestion also. People have to remember that Walter doesn't like adding any new keywords. Reuse of "scope" may be the best solution here. Are there any drawbacks? Does it fit the intended meaning and purpose appropriately? It seems to.

Given the suggested placement, I assume it would be illegal to reassign a 'scope' reference to another object? ie. class C {} scope C var = new C(); var = new C(); Assuming a reassignment is allowed, I assume the original object would not be destroyed on scope exit? Basically, I'm wondering whether the 'scope' qualifier is attached to the reference or to the referent. Sean
Jul 27 2006
parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Sean Kelly wrote:
 John Reimer wrote:
 
 On Wed, 26 Jul 2006 02:52:06 -0700, Hasan Aljudy 
 <hasan.aljudy gmail.com> wrote:

 vote++;
 //me likes

I am sympathetic to the "scope" suggestion also. People have to remember that Walter doesn't like adding any new keywords. Reuse of "scope" may be the best solution here. Are there any drawbacks? Does it fit the intended meaning and purpose appropriately? It seems to.

Given the suggested placement, I assume it would be illegal to reassign a 'scope' reference to another object? ie. class C {} scope C var = new C(); var = new C(); Assuming a reassignment is allowed, I assume the original object would not be destroyed on scope exit? Basically, I'm wondering whether the 'scope' qualifier is attached to the reference or to the referent. Sean

Maybe we could decide that based on the keyword's placement: class C { int m_i; this(int i) { m_i = i; } int i() { return m_i; } } scope C a = new C(1); // Destroy 'a' at end of scope C b = a; // b is another reference to 1. It will be invalid at the // end of scope, except: a = new C(2); // No, whoops! Destroy 2 at end of scope. // 1 is now referenced by b alone. return b; // Allowed! The reference 'a' will no longer destroy 1. return a; // NOT allowed! a is a scoped reference The alternative: C a = scope new C(1); // Destroy 1 at end of scope. C b = a; // b is another reference to 1, which will be destroyed // at the end of scope. a = new C(2); // A new, plain-old GCed instance. return b; // NOT allowed! 1 is invalid after this scope. return a; // Okay. a is a reference to a regular object. Maybe we could allow both? -- Kirk McDonald Pyd: Wrapping Python with D http://dsource.org/projects/pyd/wiki
Jul 27 2006
parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Kirk McDonald wrote:
 Maybe we could decide that based on the keyword's placement:
 
 class C {
     int m_i;
     this(int i) { m_i = i; }
     int i() { return m_i; }
 }
 
 scope C a = new C(1); // Destroy 'a' at end of scope
 C b = a; // b is another reference to 1. It will be invalid at the
          // end of scope, except:
 a = new C(2); // No, whoops! Destroy 2 at end of scope.
               // 1 is now referenced by b alone.
 return b; // Allowed! The reference 'a' will no longer destroy 1.
 return a; // NOT allowed! a is a scoped reference
 
 The alternative:
 
 C a = scope new C(1); // Destroy 1 at end of scope.
 C b = a; // b is another reference to 1, which will be destroyed
          // at the end of scope.
 a = new C(2); // A new, plain-old GCed instance.
 return b; // NOT allowed! 1 is invalid after this scope.
 return a; // Okay. a is a reference to a regular object.
 
 Maybe we could allow both?
 

Sounds reasonable to me, and potentially quite useful (even if often primarily for self-documenting code design, as I suspect in the vast majority of use-cases the effect will be identical). I also think it might very well be reasonable to disallow using 'scope' in tandem with either of 'static' or 'const' as the meaning is... well, questionable. Except perhaps for 'static' in the sole case of recursive functions, in which case I suppose the entity exists until the entire call-stack has unwound. Potentially useful. Allowing 'scope auto' seems harmless, although redundant since 'scope' as a storage class should allow for type-inference via precedance alone. -- Chris Nicholson-Sauls
Jul 28 2006
prev sibling next sibling parent Juan Jose Comellas <jcomellas gmail.com> writes:
I think "local" may be a better name. At least I don't think I have ever
used a variable with that name.


kris wrote:

 Don has a good point: changing to "var" would cause conflict with
 existing variable-names.
 
 Chad et. al. also have a good point about the conflict regarding static
 opCall() (via the lack of a "new" keyword). I suspect many people find
 the use of "new" to be indicative of allocation, and breaking this
 consistency may have a detrimental effect? Further, it was noted that a
 missing "new" can only be used at the instantiation site -- not at the
 class decl -- thus, D would be losing an existing feature.
 
 I suspect you could count the current number of raii-class uses on a few
 hands, whereas the use of "auto" for implied-type is pretty darned
 popular -- and rightly so, since it's really very, very useful. Changing
 the raii style to use a different keyword, whilst retaining implied-type
 "auto" would be an almost imperceptible change?
 
 Thus, it would appear to make sense to retain "auto" for implied-type,
 and introduce something *else* for automatic cleanup at end-of-scope
 (and also as a class attribute). how about reusing the "scope" keyword?
 
 void main()
 {
    auto i = 10;
    auto foo = new Foo;
    auto scope bar = new Bar;
    auto scope wumpus = new Wumpus;
 }
 
 class Foo {}
 
 class Bar {}
 
 scope class Wumpus {}

Jul 27 2006
prev sibling next sibling parent "Andrew Fedoniouk" <news terrainformatica.com> writes:
 void main()
 {
   auto i = 10;
   auto foo = new Foo;
   auto scope bar = new Bar;
   auto scope wumpus = new Wumpus;
 }

Conceptually 'auto' as a scope variable indicator is redundant. In 'ideal D world' struct shall have ctor/dtor and entities required stack allocation shall be declared as structs - not classes. So if you need pure stack allocated object use struct with dtor. And if you need class instance to be managed by stack variable use simple struct based smart pointer: struct local(T) { T ptr; void opAssign(T t) { ptr = t; } ~this() { delete ptr; } } void main() { local!(Bar) bar = new Bar; // opAssign invovation ... do something ... } // implicit dtor invocation happens here -> delete bar.ptr Andrew Fedoniouk. http://terrainformatica.com
Jul 27 2006
prev sibling next sibling parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
kris wrote:
 Thus, it would appear to make sense to retain "auto" for implied-type, 
 and introduce something *else* for automatic cleanup at end-of-scope 
 (and also as a class attribute). how about reusing the "scope" keyword?
 
 void main()
 {
   auto i = 10;
   auto foo = new Foo;
   auto scope bar = new Bar;
   auto scope wumpus = new Wumpus;
 }

I've argued in the past about being able to elide the 'new' keyword entirely. I like the Python semantics, where 'calling' a class is synonymous with calling a factory function that returns instances of the class. The 'new' keyword is just redundant... until you remember that D has static opCall. So, without imposing an arbitrary restriction of disallowing static opCall for classes (but not for structs!), or saying e.g. that you have to say "new" for any class with static opCall defined for it (which would just be a huge headache)... I think this is the best solution. -- Kirk McDonald Pyd: Wrapping Python with D http://dsource.org/projects/pyd/wiki
Jul 27 2006
prev sibling next sibling parent reply "Andrei Khropov" <andkhropov nospam_mtu-net.ru> writes:
kris wrote:

 Don has a good point: changing to "var" would cause conflict with existing
 variable-names.
 
 Chad et. al. also have a good point about the conflict regarding static
 opCall() (via the lack of a "new" keyword). I suspect many people find the
 use of "new" to be indicative of allocation, and breaking this consistency
 may have a detrimental effect? Further, it was noted that a missing "new" can
 only be used at the instantiation site -- not at the class decl -- thus, D
 would be losing an existing feature.

Agreed. I also don't think 'missing new' proposal is good.
 
 I suspect you could count the current number of raii-class uses on a few
 hands, whereas the use of "auto" for implied-type is pretty darned popular --
 and rightly so, since it's really very, very useful. Changing the raii style
 to use a different keyword, whilst retaining implied-type "auto" would be an
 almost imperceptible change?
 
 Thus, it would appear to make sense to retain "auto" for implied-type, and
 introduce something else for automatic cleanup at end-of-scope (and also as a
 class attribute). how about reusing the "scope" keyword?
 
 void main()
 {
   auto i = 10;
   auto foo = new Foo;
   auto scope bar = new Bar;
   auto scope wumpus = new Wumpus;
 }

Looks ok to me, but should be in the reverse order I think: -------------------------------------------------------------- void main() { auto i = 10; auto foo = new Foo; scope auto bar = new Bar; scope auto wumpus = new Wumpus; } -------------------------------------------------------------- and with the current D policy of type inference when 'static' or 'const' is enough for declaration this should be also legal: -------------------------------------------------------------- scope bar = new Bar; -------------------------------------------------------------- -- AKhropov
Jul 27 2006
parent reply kris <foo bar.com> writes:
Andrei Khropov wrote:
 kris wrote:
 
 
Don has a good point: changing to "var" would cause conflict with existing
variable-names.

Chad et. al. also have a good point about the conflict regarding static
opCall() (via the lack of a "new" keyword). I suspect many people find the
use of "new" to be indicative of allocation, and breaking this consistency
may have a detrimental effect? Further, it was noted that a missing "new" can
only be used at the instantiation site -- not at the class decl -- thus, D
would be losing an existing feature.

Agreed. I also don't think 'missing new' proposal is good.

Someone noted that x = SomeName(); is confusing, since it doesn't convey whether a class is instantiated, or a function is called. That's part of the issue noted above, and it becomes worse when dropping the optional parens x = SomeName; Whereas it is still perfectly meaningful when using new instead: x = new SomeName;
I suspect you could count the current number of raii-class uses on a few
hands, whereas the use of "auto" for implied-type is pretty darned popular --
and rightly so, since it's really very, very useful. Changing the raii style
to use a different keyword, whilst retaining implied-type "auto" would be an
almost imperceptible change?

Thus, it would appear to make sense to retain "auto" for implied-type, and
introduce something else for automatic cleanup at end-of-scope (and also as a
class attribute). how about reusing the "scope" keyword?

void main()
{
  auto i = 10;
  auto foo = new Foo;
  auto scope bar = new Bar;
  auto scope wumpus = new Wumpus;
}

Looks ok to me, but should be in the reverse order I think: -------------------------------------------------------------- void main() { auto i = 10; auto foo = new Foo; scope auto bar = new Bar; scope auto wumpus = new Wumpus; } -------------------------------------------------------------- and with the current D policy of type inference when 'static' or 'const' is enough for declaration this should be also legal: -------------------------------------------------------------- scope bar = new Bar; --------------------------------------------------------------

Yes, thankyou ~ I'd forgotton about that groovy option: void main() { auto i = 10; auto foo = new Foo; scope bar = new Bar; scope wumpus = new Wumpus; } class Foo {} class Bar {} scope class Wumpus {} // can only be used as a scope'd instance
Jul 28 2006
parent "Andrei Khropov" <andkhropov nospam_mtu-net.ru> writes:
kris wrote:

 Someone noted that
 
  x = SomeName();
 
 is confusing, since it doesn't convey whether a class is instantiated, or a
 function is called. That's part of the issue noted above, and it becomes
 worse when dropping the optional parens
 
  x = SomeName;
 
 Whereas it is still perfectly meaningful when using new instead:
 
  x = new SomeName;

Yes, that's an essential flaw in this proposal. Another one was mentioned in digitalmars.D/40740 : <quote> But how does this proposed syntax handle variable-length arrays? char[] a = read(filename); Is 'a' destroyed at end of scope? </quote> So we'll lose the ability to initialize scope variables by function return value. -- AKhropov
Jul 28 2006
prev sibling next sibling parent "Andrei Khropov" <andkhropov nospam_mtu-net.ru> writes:
<IMHO>

I recently thought about using 'scoped' instead of 'scope'.
Yes, it's one extra letter but improved readability (IMHO):

----------------------------------------------------
  scope i = 1;    // is read like 'i is a scope'
----------------------------------------------------
  scoped i = 1;    // is read like 'i is scoped' 
----------------------------------------------------

and
----------------------------------------------------
  scope class Bar{ ... 
----------------------------------------------------
  scoped class Bar{ ...   // is read like 'Bar is a scoped class' 
----------------------------------------------------


and current uses of scope are also replaced (also it's consistent with the form
'synchronized')
:

----------------------------------------------------
	scope(exit) Statement
	scope(success) Statement
	scope(failure) Statement
----------------------------------------------------
changed to
----------------------------------------------------
	scoped(exit) Statement   // is read like 'this statement is scoped at exit'
	scoped(success) Statement
	scoped(failure) Statement
----------------------------------------------------

(there's no 'scoped' verb in English AFAIK but it looks very natural and
understandable)

</IMHO>

Does anybody use 'scoped' as identifier?

-- 
AKhropov
Jul 28 2006
prev sibling parent Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
kris wrote:
 Don has a good point: changing to "var" would cause conflict with 
 existing variable-names.
 

 
 I suspect you could count the current number of raii-class uses on a few 
 hands, whereas the use of "auto" for implied-type is pretty darned 
 popular -- and rightly so, since it's really very, very useful. Changing 
 the raii style to use a different keyword, whilst retaining implied-type 
 "auto" would be an almost imperceptible change?
 
 Thus, it would appear to make sense to retain "auto" for implied-type, 
 and introduce something *else* for automatic cleanup at end-of-scope 
 (and also as a class attribute). how about reusing the "scope" keyword?
 
 void main()
 {
   auto i = 10;
   auto foo = new Foo;
   auto scope bar = new Bar;
   auto scope wumpus = new Wumpus;
 }
 
 class Foo {}
 
 class Bar {}
 
 scope class Wumpus {}
 

Up to now, I favored the following keyword proposals: "auto" -> for RAII (autoraii or raiiauto) "var" -> for implicit type deduction. (autotype) The idea that autotype is the most used auto notion, and as such should be the one not to change it's keyword has no support from me. (Although I agree Walter I very resilient towards keyword changes...) When I think the name "auto", I think the most close meaning is that of automatic allocation/decallocation (raiiauto) and not implicit type deduction. And I quite deslike the name "scope" (or even "scoped") for raiiauto, (subjective point) As for autotype, exactly because it is used often I liked the fact that "var" is one character shorter. I also liked that it was the same as C# 3.0. But I do agree there is some strangeness to see "var" used as such keyword for type deduction, so I wasn't 100% happy. How about "def" for autotype keyword? It's still one char shorter, and I think the name is pretty nice: def n = 42; def foo = new Foo(); The syntax similarity to dynamic languages is also somewhat... appealing :) -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 29 2006