July 27, 2006
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?
>>  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")


Ok.

>>> 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.

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).
>>  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?

>>> 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.

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
July 27, 2006
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
July 27, 2006
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.
> One should also consider future users of D since we haven't even reached 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.

Agreed ( it's also one letter shorter :-) )

-- 
AKhropov
July 28, 2006
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 guess there are regular "var" users then but when I said "programmers"
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?)
'x' and 'i' are often used in mathematical formulas and contexts so they
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
To be frank I don't get your point here. "static", "auto" and "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++.
Yes, but not in the context of type inference. So the C "auto" is totally different from it's current D counterpart.

Regards,
Nils


July 28, 2006
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 guess there are regular "var" users then but when I said "programmers"
> 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?)
> 'x' and 'i' are often used in mathematical formulas and contexts so they
> 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
> To be frank I don't get your point here. "static", "auto" and "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++.
> Yes, but not in the context of type inference. So the C "auto" is 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?
July 28, 2006
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);
Actually yes. I find it to be clearer than just static x.

> ? Surely not. 'const var' would be an abomination!
I agree on that. "const x = 5;" is expressive enough in its own way. But 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.
Also agreed. I find "local" much better than "auto". But I'm afraid we 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".
You have a point. But it is definitely the most often used type and what 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.
Sounds good to me.


>>> Agreed, but the 'auto' thing ultimately comes from C, not C++.
>> Yes, but not in the context of type inference. So the C "auto" is 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 that's the same ugly legacy. I think D should drop things that 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?
Good question. But my guess is that for variables it's something like what you described above and that "const" does not get a "var". But it's just a guess.

Regards,
Nils
July 28, 2006
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

July 28, 2006
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
July 28, 2006
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.
July 28, 2006
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 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.
> 
> 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 ;)
>>>  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.
> 
> 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