August 18, 2008 Re: D newb | ||||
|---|---|---|---|---|
| ||||
Posted in reply to JAnderson | "JAnderson" wrote
> Steven Schveighoffer wrote:
>> "bearophile" wrote
>>> Robert Fraser:
>>>> scope Foo f = new Foo();
>>>>
>>>> The "scope" keyword in the declaration says to the compiler "this will not escape the function" thus creating the data on the stack. "f" is still a reference type in this case, however (although it may not be implemented as a reference -- that's up o the compiler).
>>> But the 'scope' works only in some situations, the original poster can take a look at the docs about 'scope'.
>>>
>>> My question: does the compiler raise a compilation error if the 'scope' keyword is used where the compiler can't actually allocate the class on the stack? (if not, then I think it may be better for the compiler to raise such error, avoiding the illusion of efficiency).
>>
>> In what situations does it not work?
>>
>> As long as the class is not too large for the stack (which is very unlikely), it should be able to allocate.
>>
>> -Steve
>
> If the class has a component sub-class the component may be heap allocated. I don't agree with making that an error though.
If the class allocates anything dynamically, it would be heap allocated. I think there's no way around that.
for instance, C++'s vector class can be stack allocated, but the elements will be heap allocated.
However, a frequently asked-for enhancement is to allow scope members which could be allocated as part of the class' space (and therefore would be allocated on the stack in the case of a scope allocated class).
-Steve
| |||
August 18, 2008 Re: D newb | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | bearophile Wrote: > > public int m_int = 0; > This is enough: > public int m_int; > Because variables are initialized to .init by default (and there's a way to avoid that), and int.init is 0. So every variable is 0 initialized? > > int main(string[] args) > > You can use this, because the return value is automatic: > void main() If I want to return a value other than 0, how do I do it? > To print writef/writefln is generally better, because typesafe (but it makes your executable fatter): > writefln(foo %d", f.m_int); What does that mean - to be typesafe? Can you give me a real example of where writef() is better than printf(). I'm looking for a good D tutorial. Something that would have all these answers. Can you recommend one? I've been writing C for a dozen years and C++ for a few, as well as other stuff here and there. Tim | |||
August 18, 2008 Re: D newb | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Tim H | "Tim H" wrote > bearophile Wrote: > > >> > public int m_int = 0; >> This is enough: >> public int m_int; >> Because variables are initialized to .init by default (and there's a way >> to avoid that), and int.init is 0. > > So every variable is 0 initialized? No, every variable is initialized to a default. Most of the time, this is zero (or null). However, sometimes, it is not. For instance, floating point numbers are initialized to NaN. If you want to know the initial value, it is stored as the inherent 'init' property. So for example, all ints are initialized to int.init (unless you override that with an assignment). >> > int main(string[] args) >> >> You can use this, because the return value is automatic: >> void main() > > If I want to return a value other than 0, how do I do it? The way you originally had it. I think bearophile was saying that in your particular example, you don't need to use it, because you never return anything but zero (EXIT_SUCCESS). > >> To print writef/writefln is generally better, because typesafe (but it >> makes your executable fatter): >> writefln(foo %d", f.m_int); > > What does that mean - to be typesafe? Can you give me a real example of where writef() is better than printf(). Sure, if you do: printf("foo %d\n", "hello"), you will get the pointer of hello as an integer. if you do writef("foo, %d\n", "hello"), you get a type exception (I think), because writef is passed the type of all its arguments. A better example: printf("foo %s\n", 0), which gives you a segfault. With writef, %s is a 'catch all'. It means, 'check the type of the argument to see how to print it', and in the case: writef("foo %s\n", 0), you will get a 0. Most of the other % types are for formatting, like if you wanted a certain precision floating point, or to 0-pad, etc. Most of the time, you can just use %s: writef("%s, %s is an int, %s is a float, %s is a long", "hi", 5, 4.3, 1000000000000); > > I'm looking for a good D tutorial. Something that would have all these answers. Can you recommend one? I've been writing C for a dozen years and C++ for a few, as well as other stuff here and there. As I only use Tango (http://www.dsource.org/projects/tango), I don't know of tutorials that uses Phobos, but I would imagine there should be something on the digitalmars site. There's plenty of tutorials and instruction (and a book in print) if you want to use Tango. -Steve | |||
August 18, 2008 Re: D newb | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Sun, 17 Aug 2008 20:09:19 -0400, bearophile wrote: > Tim H., others have already answered your main question. Regarding your code: > > Add the list of names you want to use, importing just the names you need, avoiding namespace pollution: import std.c.stdlib: writefln; > > >> public int m_int = 0; > This is enough: > public int m_int; > Because variables are initialized to .init by default (and there's a way > to avoid that), and int.init is 0. > > >> int main(string[] args) > > You can use this, because the return value is automatic: void main() > > > To print writef/writefln is generally better, because typesafe (but it > makes your executable fatter): writefln(foo %d", f.m_int); > > Bye, > bearophile http://www.dsource.org/ Most everything there is for D 1.0 many tutorials/examples written before its release and only for Phobos (which you are using), but still valid. | |||
August 18, 2008 Re: D newb | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Tim H | Tim H wrote: ... > I'm looking for a good D tutorial. Something that would have all these answers. Can you recommend one? I've been writing C for a dozen years and C++ for a few, as well as other stuff here and there. > > Tim There is one wiki which contains a lot of information (probably the most) and further links: http://prowiki.org/wiki4d/wiki.cgi It has a section about learning D, I'd recommend reading 'text in d'. Perhaps the sections about porting C and C++ to D are also worthwhile in your case, to see differences. Furthermore, the digitalmars site has lots of good documentation, not only the spec but the articles are good too. Some articles are specific for C++ users. The book about Tango is really mostly a book about D, so that's good too. There is a sample chapter you may find useful here: http://www.gamedev.net/reference/programming/features/DTangoCh2/ | |||
August 18, 2008 Re: D newb | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Tim H | Tim H schrieb: > I'm looking for a good D tutorial. Something that would have all these answers. Can you recommend one? I've been writing C for a dozen years and C++ for a few, as well as other stuff here and there. > > Tim Porting C++ to D at: http://prowiki.org/wiki4d/wiki.cgi?PortingFromCxx HTH, Bjoern | |||
August 18, 2008 Re: D newb | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Steven Schveighoffer: > The way you originally had it. I think bearophile was saying that in your particular example, you don't need to use it, because you never return anything but zero (EXIT_SUCCESS). This too works, even if it looks a bit strange: void main() { return 1 } > Most of the time, you can just use %s: > writef("%s, %s is an int, %s is a float, %s is a long", "hi", 5, 4.3, > 1000000000000); In some situations you can also just avoid using formatting: writef("The result is ", r0, " after ", n, " iterations."); But you have to be careful that the first string doesn't contain % for other purposes. To avoid that D 2.x has write/writeln (or you can use my better put/putr functions). (I think I now know enough of D that I may be able to start writing a "D best practices" web page). Bye, bearophile | |||
August 18, 2008 Re: D newb | ||||
|---|---|---|---|---|
| ||||
Posted in reply to JAnderson | Joel Anderson:
> > bearophile:
> >> My question: does the compiler raise a compilation error if the 'scope' keyword is used where the compiler can't actually allocate the class on the stack? (if not, then I think it may be better for the compiler to raise such error, avoiding the illusion of efficiency).
>
> If the class has a component sub-class the component may be heap allocated. I don't agree with making that an error though.
May I ask you why you don't like that as an error?
Generally I don't like undefined situations, if I add the 'scope' keyword I want the class to be stack-allocated, and I assume the compiler does that. Then the layout of the memory used by the code is different, and I can for example take care to avoid a stack overflow. If the compiler at compile time is able to tell me that the class can't be allocated on the stack, then I think the program has to not compile until I remove the 'scope' keyword there. This makes the code reflect what the program actually does.
Bye,
bearophile
| |||
August 19, 2008 Re: D newb | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | bearophile wrote:
> Joel Anderson:
>>> bearophile:
>>>> My question: does the compiler raise a compilation error if the 'scope' keyword is used where the compiler can't actually allocate the class on the stack? (if not, then I think it may be better for the compiler to raise such error, avoiding the illusion of efficiency).
>> If the class has a component sub-class the component may be heap allocated. I don't agree with making that an error though.
>
> May I ask you why you don't like that as an error?
> Generally I don't like undefined situations, if I add the 'scope' keyword I want the class to be stack-allocated, and I assume the compiler does that. Then the layout of the memory used by the code is different, and I can for example take care to avoid a stack overflow. If the compiler at compile time is able to tell me that the class can't be allocated on the stack, then I think the program has to not compile until I remove the 'scope' keyword there. This makes the code reflect what the program actually does.
>
> Bye,
> bearophile
What I'm talking about is:
class A
{
}
class B
{
...
A a = new A(); // Heap Allocated
...
};
...
scope B b = new B; //B is scope allocated but A is not
Say your using someone else's class. You get latest and you using one of there classes with the word scope. They've decided to add something that is heap allocated. Now suddenly your code is not working because someone made a slight change to their interface.
Of course you might not be responsible for either pieces of code. You might be using a template from lib A to iterate over some class in lib B. Anyway what ends up happening is the code becomes very un-generic. People have to create 2 versions of everything.
I think the idea of having scope members is a good one. However if your using someone else class that has heap allocation you really have no choice. If you make this an error then your limiting that classes use.
As to the class overflowing the stack size. I think if a class is so big that that the compiler automatically heap allocates it, then there's a lot of other issues with your code or your running on some platform where it works better that way. The compiler should do what it can to make sure your code runs, slow as it may be, without logical errors.
I think you always want to tell the compiler what you want to do rather then how and let it decide the best approach. That way you get more portable code that is optimized for whatever system its going on.
-Joel
| |||
August 19, 2008 Re: D newb | ||||
|---|---|---|---|---|
| ||||
Posted in reply to JAnderson | "JAnderson" wrote
> bearophile wrote:
>> Joel Anderson:
>>>> bearophile:
>>>>> My question: does the compiler raise a compilation error if the 'scope' keyword is used where the compiler can't actually allocate the class on the stack? (if not, then I think it may be better for the compiler to raise such error, avoiding the illusion of efficiency).
>>> If the class has a component sub-class the component may be heap allocated. I don't agree with making that an error though.
>>
>> May I ask you why you don't like that as an error?
>> Generally I don't like undefined situations, if I add the 'scope' keyword
>> I want the class to be stack-allocated, and I assume the compiler does
>> that. Then the layout of the memory used by the code is different, and I
>> can for example take care to avoid a stack overflow. If the compiler at
>> compile time is able to tell me that the class can't be allocated on the
>> stack, then I think the program has to not compile until I remove the
>> 'scope' keyword there. This makes the code reflect what the program
>> actually does.
>>
>> Bye,
>> bearophile
>
> What I'm talking about is:
>
> class A
> {
>
>
> }
>
> class B
> {
> ...
> A a = new A(); // Heap Allocated
> ...
> };
>
>
> ...
>
> scope B b = new B; //B is scope allocated but A is not
>
> Say your using someone else's class. You get latest and you using one of there classes with the word scope. They've decided to add something that is heap allocated. Now suddenly your code is not working because someone made a slight change to their interface.
>
The compiler cannot know when a constructor will decide to heap-allocate. So it cannot predict whether the entire class will be stack-allocated. Once the constructor is called, you cannot extend the previous stack frame (without a lot of extra work), and even then, it cannot be sure that the calling function won't use that stack space later in the function. I think what you ask for is impossible to implement, and impossible to detect.
-Steve
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply