October 28, 2005
In article <djssee$1b40$1@digitaldaemon.com>, Bruno Medeiros says...
>
>"Would such a design support returning classes by value?"
>Why did everyone suddenly started talking about implementind value
>semantics for classes? It has nothing to do with the current
>design/issue (which is RAII and auto-type). Just because the new RAII
>proposal has a syntax similiar to C++'s value objects, it doesn't mean
>they are anywhere near the same.

I asked mostly because the two go hand-in-hand and I wanted to be sure I understood what Walter was proposing.  I've given this issue some thought however, and I think Walter is right for avoiding value semantics for classes with this change.  I can't think of a way around the need for a copy ctor and assignment operator support, and smart pointers also typically require an overloaded -> operator, which would be an overloaded dot operator in D (a horrifying idea IMO).  I have also seen arguments that shared_ptr does not offer deterministic destruction so it's really more like a poor man's GC in most cases--the real strength of shared_ptr lies in its ability to execute arbitrary code on destruction, which we can do easily enough with auto classes accepting a delegate.  I've realized that most times I want stack-based classes it's either because I want scope-specific RAII or because I want to avoid the use of heap allocation for one reason or another, and Walter's proposal provides this.  I personally don't believe that D has this now because alloca() is a nonstandard C extension, and is therefore nonportable (it's also done at runtime, which is unnecessary in most cases).  The semantic issue makes sense in this light because classes will never be value types, unlike all other types in D.  So long as the new construction method is extended to work for all types (besides struct), I'll be quite happy:

T v = T(val);
T v = new T(val);

(assume this is template code so T is actually a pointer type for non-class
values)

And if not, I'll stick to using template wrappers for this stuff :p


Sean


October 28, 2005
"Ivan Senji" <ivan.senji_REMOVE_@_THIS__gmail.com> wrote in message news:djsfm9$rr8$1@digitaldaemon.com...
> Syntax is great with auto because it simplifies things alot, but for x=1; to be a declaration would be a big mistake, i never liked those languages, things like that cause bugs that are really hard to find if you for example misspell something, or if you later need to find the places in code where you declare new objects it is imposible.

You're right. Declarations that have the same syntax as expressions or other statements lead to the classic "DO10I" bug.


October 28, 2005
"James Dunne" <james.jdunne@gmail.com> wrote in message news:djtfg6$1u2s$1@digitaldaemon.com...
> Can we have a new warning for use of potentially uninitialized variable?
>   I know this might cause problems with current code relying on D's
> default initialization values.

As you say, that kinda undermines a lot of the way D is oriented.

> Anyway, I have a mathematical model which makes exclusive use of the double floating-point type, and doubles are initialized to NaN in D by default.  Consequently, propogating NaNs through the calculation makes it hard to track down where the first NaN came from - hence, which variable in particular was forgotten to be initialized.
>
> There are a lot of variables in this model, and debugging is not easy since it is running under Excel (from VBA) as an external Win32 DLL, so no printf tricks will track the guy down unfortunately.

When I needed to use printf in a DLL with no console, I'd have the printf write to a file. That worked well.

> Anyway, I think my point still stands.  Use of uninitialized variable warning, please?  Or perhaps a way to trap usage of a NaN in a calculation and break into the debugger - THAT would make debugging MUCH faster, i.e. use SNANs instead of QNANs (signaling/noisy vs. quiet).

Some strategically placed assert(!isnan(x)) expressions should help.


October 28, 2005
In article <djsf79$r5t$1@digitaldaemon.com>, Ivan Senji says...
>
>Dave wrote:
>> In article <djrbo0$lkk$1@digitaldaemon.com>, Ivan Senji says...
>>>As it would in C++, at the end of scope c is dead.
>>>
>> 
>> 
>> Yes, 'c' is dead, but before that the copy ctor is called (implicit or explicit) and that temporary copy is returned; so it really isn't undefined behaviour although it can hide bugs that seem like it <g>
>> 
>
>Copy ctor? D doesn't hava a copy ctor. c is a reference to a location on the stack, and when you exit the method and the objects is destroyed you really shouldn't be using that memory location.
>

Ok - how's this:

"Yes, 'c' is dead, but before that the copy ctor is called (implicit or explicit) and that temporary copy is returned; so it really isn't undefined behaviour

/in C++/

although it can hide bugs that seem like it <g>"

Since my reply was right after you mentioned C++ I thought it would be clear that the reference was to C++.

>Can hide bugs? It is a bug.
>
>> I think the prev. poster was just asking (as I did earlier with an example) if Walter has some magic that would allow this? Like how stack allocated D structs are returned by value (shallow copy of heap members), which D can usually get away with because of the GC.
>
>Only Walter knows. But structs are very different from classes.
>
>> ...


October 28, 2005
In article <djssee$1b40$1@digitaldaemon.com>, Bruno Medeiros says...
>
>Dave wrote:
>> So, for stack alloc. classes (excluding RAII), couldn't an ...
>Walter has said this here before: stack allocated classes/objects and RAII classes/objects are *the same*. There is no stack allocated classes/objects that are not RAII.
>
>> In article <djrt8q$2o2o$1@digitaldaemon.com>, Walter Bright says...
>>>
>>>"Sean Kelly" <sean@f4.ca> wrote in message
>>>Would such
>>>
>>>>a design support returning classes by value?  ie.
>>>>
>>>>MyClass getInstance() {
>>>>MyClass c = MyClass();
>>>>return c;
>>>>}
>>>
>>>Returning references to stack variables is wrong, wrong, wrong <g>.
>>>
>"Would such a design support returning classes by value?"
>Why did everyone suddenly started talking about implementind value
>semantics for classes? It has nothing to do with the current
>design/issue (which is RAII and auto-type). Just because the new RAII
>proposal has a syntax similiar to C++'s value objects, it doesn't mean
>they are anywhere near the same.
>
>
>> What happens with structs now? They are copied by value, but are not deep copied. ...
>What follows is a reply to also some other comments in others posts: Structs have value semantics because they are structs, *not because* they are stack allocated. Thus just because we have stack allocated

Yep, but classes having value semantics was not necessarily what I was implying.

>objects (RAII) doesn't mean they should have value semantics as well!

I'm not really asking for value semantics, I'm asking /if/ classes allocated on the stack can be returned 'safely' in a defined way, and I suggested a way to implement it that would basically allow the same syntax whether or not a class object was heap or stack allocated.

>D's objects follow a reference model (all of them), and any discussion

No, they don't - structs can be considered 'objects' as can any native type - especially when you consider the implications of the current design on generic programming techniques. For example, for many algorithms you would have to develop two sets of templates or use compiler conditionals like static if everywhere to support both class and struct 'objects' with the same template declarations. That is not what I'd like to call 'generic' programming.

>regarding that, is off-topic for this thread.
>

Huh? Asking whether or not the new syntax that Walter put out here and has been recently discussed (and replied to) would let us return class objects allocated on the stack is completely within the context of this discussion since it was not real clear whether or not RAII and/or class object stack allocation would require 'auto' declaration or not.

>-- 
>Bruno Medeiros - CS/E student
>"Certain aspects of D are a pathway to many abilities some consider to
>be... unnatural."


October 28, 2005
Dave wrote:
> In article <djsf79$r5t$1@digitaldaemon.com>, Ivan Senji says...
> 
>>Dave wrote:
>>
>>>In article <djrbo0$lkk$1@digitaldaemon.com>, Ivan Senji says...
>>>
>>>>As it would in C++, at the end of scope c is dead.
>>>>
>>>
>>>
>>>Yes, 'c' is dead, but before that the copy ctor is called (implicit or explicit)
>>>and that temporary copy is returned; so it really isn't undefined behaviour
>>>although it can hide bugs that seem like it <g>
>>>
>>Copy ctor? D doesn't hava a copy ctor. c is a reference to a location on the stack, and when you exit the method and the objects is destroyed you really shouldn't be using that memory location.
>>
> 
> 
> Ok - how's this:
> 
> "Yes, 'c' is dead, but before that the copy ctor is called (implicit or
> explicit) and that temporary copy is returned; so it really isn't undefined
> behaviour 
> 
> /in C++/
> 
> although it can hide bugs that seem like it <g>"
> 
> Since my reply was right after you mentioned C++ I thought it would be clear
> that the reference was to C++.
> 

Sorry, my mistake :)
But the program segment in question i see as this code in C++:

MyClass* getInstance() {
MyClass c();
return &c;
}

And we can agree that this is not good code.

> 
>>Can hide bugs? It is a bug.
>>
>>
>>>I think the prev. poster was just asking (as I did earlier with an example) if
>>>Walter has some magic that would allow this? Like how stack allocated D structs
>>>are returned by value (shallow copy of heap members), which D can usually get
>>>away with because of the GC.
>>
>>Only Walter knows. But structs are very different from classes.
>>
>>
>>>...
> 
> 
> 
October 28, 2005
Bruno Medeiros wrote:
> Ivan Senji wrote:
> 
>> Bruno Medeiros wrote:
>>
>>>
>>> auto c = new C();   // c is not RAII , is auto-typed
>>> auto C d = new C(); // c is RAII, is not auto-typed
>>>
>>
>> Shouldn't it be:
>>
>> type c = new type(args); //type not infered, no RAII
>> auto c = new type(args); //type infered, no RAII
>> type c = type(args);     //type not infered, RAII
>> auto c = type(args);     //type infered, RAII
>>
>> At least this is what i figured out it should be, so:
>> auto means type is infered, no new means RAII.
>>
> 
> No it shouldn't be. I said before (here: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.announce/1771 ) that I was talking about the current DMD.137 situation in that post, not Walter's new proposal.
> 

Sorry, i really was tired when reading these posts :)

> 
October 29, 2005
In article <djtk8t$22lg$2@digitaldaemon.com>, Walter Bright says...
>
>
>"James Dunne" <james.jdunne@gmail.com> wrote in message news:djtfg6$1u2s$1@digitaldaemon.com...
>> Can we have a new warning for use of potentially uninitialized variable?
>>   I know this might cause problems with current code relying on D's
>> default initialization values.
>
>As you say, that kinda undermines a lot of the way D is oriented.
>

Well, I think the case is exceptional for IEEE floating point types in D.  If I assume correctly, you've initialized them to _quiet_ NaNs so that it'd be easy to detect when they are used in their "uninitialized" state.  Since the IEEE spec defines that no _signaling_ NaN will be produced by any floating point operation, and that SNaNs are strictly for assignment purposes, it seems logical to initialize floating point values to signaling NaNs instead of quiet NaNs. I'm sure you're well aware of this, and perhaps it might have been a minor oversight.  However, if there was some conscious decision made as whether to use QNaNs over SNaNs I'd be interested to hear some reasoning.

FWIW, I'm not that well read on the topic of the IEEE standard, but I did do my homework! =)  I came across 'rumors', if you will, that supporting signaling NaNs is tough to do in implementation because I guess the spec is unclear on specific details of implementation and certain usage cases.

>> Anyway, I have a mathematical model which makes exclusive use of the double floating-point type, and doubles are initialized to NaN in D by default.  Consequently, propogating NaNs through the calculation makes it hard to track down where the first NaN came from - hence, which variable in particular was forgotten to be initialized.
>>
>> There are a lot of variables in this model, and debugging is not easy since it is running under Excel (from VBA) as an external Win32 DLL, so no printf tricks will track the guy down unfortunately.
>
>When I needed to use printf in a DLL with no console, I'd have the printf write to a file. That worked well.
>

Thought of doing that, yes...

>> Anyway, I think my point still stands.  Use of uninitialized variable warning, please?  Or perhaps a way to trap usage of a NaN in a calculation and break into the debugger - THAT would make debugging MUCH faster, i.e. use SNANs instead of QNANs (signaling/noisy vs. quiet).
>
>Some strategically placed assert(!isnan(x)) expressions should help.
>

Yes, but hopefully catching a floating-point exception from usage of a signaling NaN would track it down even better... ?

Regards,
James Dunne
October 29, 2005
Ivan Senji wrote:
> Yuck.
> With stack based class objects we are getting big bunch of problems with returning destructed objects. Is it really a good idea to have stack-based classes? We have lived without them for a long time in D.
> And although i can see that they have some advantages (like speed) but it looks to me they bring big problems to the language.

I think the most important use of stack based objects is if you want something to automatically happen when the scope is left.

For example (using pseudo-syntax to avoid the confusion of "auto"):

{
local MutexLock l=MutexLock(myMutex);
...stuff
// automatically release mutex
}

Having this ability can be invaluable for preventing bugs that are very hard to find.

The solution for preventing dangling references for stack based objects would be to make "stack-based" a type modifier without implicit conversion to non-stack-based types. For example:

local MutexLock l=MutexLock(myMutex);

MutexLock x=l;	// error because x is not a stack-reference.

local MutexLock y=l; // ok. Note that y cannot become a dangling
                     // reference because it is either in the same
                     // scope as l or in an inner scope. So y always
                     // goes out of scope before l.

MutexLock x=cast(local MutexLock)l;	//ok? should be allowed IMHO


Stack references should only be allowed as local variables and function parameters. Everything else would lead to dangling references.

Note that implicit conversion from non-stack reference to stack reference is not a problem.

I just realized that such a type modifier would also solve another common programming problem. You often have methods with arguments that should only be used during the execution of the method. I.e. you do not want a reference to the argument to be stored and used again later, possibly because the object might be in an invalid state at that time.

Having a "local" type modifier could help to enforce this. If the function argument is "local" then it can only be stored in other local variables of that function. So it is impossible for the implementor of the method to accidently access the object again after the function returns.

Hauke




October 29, 2005
James Dunne wrote:

> Well, I think the case is exceptional for IEEE floating point types
> in D.  If I assume correctly, you've initialized them to _quiet_ NaNs
> so that it'd be easy to detect when they are used in their
> "uninitialized" state.  

> Since the IEEE spec defines that no
> _signaling_ NaN will be produced by any floating point operation, and
> that SNaNs are strictly for assignment purposes, it seems logical to
> initialize floating point values to signaling NaNs instead of quiet
> NaNs.

Precisely!

I too missed the distinction when I last year studied NANs. For some embarrassing oversight, I never stopped to figure out exactly why there are two distinct NANs in the first place. (I guess I just vaguely assumed that it'd give more ways for the application programmer to deal with them.)

Even though we have "printf debugging", this would save a considerable amount of time.

And while QNANs would be propagated, SNANs should at least cause an error whenever they are stumbled upon. (This includes code that never expects to see them.)