Re: Classes or stucts :: Newbie

2010-12-21 Thread bearophile
It seems I disagree with most things you say in this thread :-)

Jonathan M Davis:

Talking about SafeD meaning memory safety makes the meaning of safety clear. 
If you try and make the term safety encompass more than that, it takes very 
little for safety to become subjective. Regardless of whether it would be 
nice if SafeD gave types of safety other than memory safety, when D 
documentation and any of the main D devs talk about safety, it is memory 
safety which is being referred to. Trying to expand the meaning beyond that 
will just cause confusion regardless of whether the non-memory safety being 
discussed is desirable or not.

SafeD is a misleading name. Names are important because they not just reflect 
how we see things, but they also shape how we see and how we will see things. 
If D will want to add overflow safety it will need to call those parts 
UltraSafeD :-)

Safety in a language is not so much subjective, just a little. Try to take a 
look at languages where safety is taken seriously, like SPARK, or even Ada.


It's trivial to get a reference or pointer to escape and make undetectable to 
the compiler. Some escape analysis can be and is done, but all it takes is 
passing a pointer or a reference to another function and the compiler can't 
determine it anymore unless it has access to the called functions body, and 
perhaps the bodies of functions that that function calls.

I think the type system can solve this problem (but where the programmer wants 
to fool the compiler or punch a hole in the type system on purpose), the not 
escaping nature of the reference has to become transitive, and the called 
function too needs the type annotation that ensure that the reference doesn't 
escape. Probably linear types are one way to do this, but there are more 
flexible ways to do it (to avoid template bloat this annotation may work as 
auto const, so in the binary only one istance of the function will be present 
even if it is once called with a reference that can't escape and it is called 
by someone else that gives a free to escape reference).

Bye,
bearophile


Re: Classes or stucts :: Newbie

2010-12-20 Thread spir
On Sun, 19 Dec 2010 21:33:56 -0500
bearophile bearophileh...@lycos.com wrote:

 So, putting classes on the stack kind of negates the whole point of having 
 both structs and classes in the first place.  
 
 This is false, the definition of D class instance doesn't specify where the 
 instance memory is allocated.

For me, the important difference is that classes are referenced, while structs 
are plain values. This is a semantic distinction of highest importance. I would 
like structs to be subtype-able and to implement (runtime-type-based) 
polymorphism.

Denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com



Re: Classes or stucts :: Newbie

2010-12-20 Thread Jonathan M Davis
On Monday 20 December 2010 01:19:31 spir wrote:
 On Sun, 19 Dec 2010 21:33:56 -0500
 
 bearophile bearophileh...@lycos.com wrote:
  So, putting classes on the stack kind of negates the whole point of
  having both structs and classes in the first place.
  
  This is false, the definition of D class instance doesn't specify where
  the instance memory is allocated.
 
 For me, the important difference is that classes are referenced, while
 structs are plain values. This is a semantic distinction of highest
 importance. I would like structs to be subtype-able and to implement
 (runtime-type-based) polymorphism.

Except that contradicts the facts that they're value types. You can't have a 
type which has polymorphism and is a value type. By its very nature, 
polymorphism requires you to deal with a reference.

C++ allows you to put classes on the stack. It even allows you to assign a 
derived type to a base type where the variable being assigned to is on the 
stack. The result is shearing. The only part assigned is the base type portion, 
and the data which is part of the derived type is lost. That's because the 
variable _is_ the base type. A value type _is_ a particular type _exactly_ and 
_cannot_ be any other type. This is distinctly different from a reference of a 
base type which points to an object which is of a derived type. In that case, 
the variable is a reference of the base type, but the object referenced is in 
fact the derived type. The indirection allows you to use the derived type as if 
it were the base type. It allows you to use polymorphism. Without that 
indirection, you can't do that.

So, you _could_ make structs have inheritance, but doing so would introduce 
shearing, which causes a number of problems. One of the main reasons that 
structs in D do _not_ have inheritance is to avoid shearing.

- Jonathan M Davis


Re: Classes or stucts :: Newbie

2010-12-20 Thread spir
On Mon, 20 Dec 2010 01:29:13 -0800
Jonathan M Davis jmdavisp...@gmx.com wrote:

  For me, the important difference is that classes are referenced, while
  structs are plain values. This is a semantic distinction of highest
  importance. I would like structs to be subtype-able and to implement
  (runtime-type-based) polymorphism.  
 
 Except that contradicts the facts that they're value types. You can't have a 
 type which has polymorphism and is a value type. By its very nature, 
 polymorphism requires you to deal with a reference.

Can you expand on this?

At least Oberon has value structs (records) with inheritance and 
polyporphism; I guess the turbo Pascal OO model was of that kind, too (unsure) 
-- at least the version implemented in freepascal seems to work fine that way. 
And probably loads of less known PLs provide such a feature.
D structs could as well IIUC: I do not see the relation with instances beeing 
implicitely referenced. (Except that they must be passed by ref to member 
functions they are the receiver of, but this is true for any kind of OO, 
including present D structs.)

(I guess we have very different notions of reference, as shown by previous 
threads.)


Denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com



Re: Classes or stucts :: Newbie

2010-12-20 Thread bearophile
Nick Voronin:

 Here is where we diverge. Choosing struct vs class on criteria of their 
 placement makes no sense to me. 

In D you use a class if you want inheritance or when you (often) need reference 
semantics, and you use a struct when you need a little value passed around by 
value or when you want a simple form of RAII or when you want to implement 
something manually (like using PIMPL), or when you want max performance (and 
you manage structs by pointer, you may even put a tag inside the stuct or the 
pointer and implement manually some kind of inheritance). With structs you have 
a literal syntax, postblits, in-place allocation, and you are free to use 
align() too.

Bye,
bearophile


Re: Classes or stucts :: Newbie

2010-12-20 Thread Jonathan M Davis
On Monday 20 December 2010 01:52:58 spir wrote:
 On Mon, 20 Dec 2010 01:29:13 -0800
 
 Jonathan M Davis jmdavisp...@gmx.com wrote:
   For me, the important difference is that classes are referenced, while
   structs are plain values. This is a semantic distinction of highest
   importance. I would like structs to be subtype-able and to implement
   (runtime-type-based) polymorphism.
  
  Except that contradicts the facts that they're value types. You can't
  have a type which has polymorphism and is a value type. By its very
  nature, polymorphism requires you to deal with a reference.
 
 Can you expand on this?
 
 At least Oberon has value structs (records) with inheritance and
 polyporphism; I guess the turbo Pascal OO model was of that kind, too
 (unsure) -- at least the version implemented in freepascal seems to work
 fine that way. And probably loads of less known PLs provide such a
 feature. D structs could as well IIUC: I do not see the relation with
 instances beeing implicitely referenced. (Except that they must be passed
 by ref to member functions they are the receiver of, but this is true
 for any kind of OO, including present D structs.)
 
 (I guess we have very different notions of reference, as shown by
 previous threads.)

Okay. This can get pretty complicated, so I'm likely to screw up on some of the 
details, but this should give you a basic idea of what's going on.

In essentially any C-based language, when you declare an integer on the stack 
like so:

int a = 2;

you set aside a portion of the stack which is the exact size of an int 
(typically 32 bits, but that will depend on the language). If you declare a 
pointer,

int* a;

then you're setting aside a portion of the stack the size of a pointer (32 bits 
on a 32 bit machine and 64 bits on a 64 bit machine). That variable then holds 
an address - typically to somewhere on the heap, though it could be to an 
address on the stack somewhere. In the case of int*, the address pointed to 
will 
refer to a 32-bit block of memory which holds an int.

If you have a struct or a class that you put on the stack. Say,

class A
{
int a;
float b;
}

then you're setting aside exactly as much space as that type requires to hold 
itself. At minimum, that will be the total size of its member variables (in 
this 
case an int and a float, so probably a total of 64 bits), but it often will 
include extra padding to align the variables along appropriate boundaries for 
the sake of efficiency, and depending on the language, it could have extra type 
information. If the class has a virtual table (which it will if it has virtual 
functions, which in most any language other than C++ would mean that it 
definitely has a virtual table), then that would be part of the space required 
for the class as well (virtual functions are polymorphic; when you call a 
virtual function, it calls the version of the function for the actual type that 
an object is rather than the pointer or reference that you're using to refer to 
the object; when a non-virtual function function is called, then the version of 
the function which the pointer or reference is is used; all class functions are 
virtual in D unless the compiler determines that they don't have to be and 
optimizes it out (typically because they're final); struct functions and stand-
alone functions are never virtual). The exact memory layout of a type _must_ be 
known at compile time. The exact amount of space required is then known, so 
that 
the stack layout can be done appropriately.

If you're dealing with a pointer, then the exact memory layout of the memory 
being pointed to needs to be known when that memory is initialized, but the 
pointer doesn't necessarily need to know it. This means that you can have a 
pointer of one type point to a variable of another type. Now, assuming that 
you're not subverting the type system (e.g. my casting int* to float*), you're 
dealing with inheritance. For instance, you have

class B : A
{
bool c;
}

and a variable of type A*. That pointer could point to an object which is 
exactly of type A, or it could point to any subtype of A. B is derived from A, 
so the object could be a B. As long as the functions are virtual, you can have 
polymorphic functions by having the virtual table used to call the version of 
the function for the type that the object actually is rather than the type that 
the pointer is.

References are essentially the same as pointers (though they may have some 
extra 
information with them, making them a bit bigger than a pointer would be in 
terms 
of the amount of space required on the stack). However, in the case of D, 
pointers are _not_ treated as polymorphic (regardless of whether a function is 
virtual or not), whereas references _are_ treated as polymorphic (why, I don't 
know - probably to simplify pointers). In C++ though, pointers are polymorphic.

Now, if you have a variable of type A*, you could do something like this:

B* b = new 

Re: Classes or stucts :: Newbie

2010-12-20 Thread bearophile
Jonathan M Davis:

 So, putting classes on the stack kind of negates the whole point of having
 both structs and classes in the first place.

Where you put the instance is mostly a matter of implementation. This is why a 
smart JavaVM is able to perform escape analysis and choose where to allocate 
the class instance.

Keep in mind that if you allocate a class on the stack or in-place inside 
another class, you don't turn it into a value, because beside the class 
instance you reserve space for its reference too (this reference may even be 
immutable, if you want).


 scoped classes are definitely not in SafeD.

Well implemented scoped classes are safe enough (compared to the other things). 
The compiler may perform escape analysis of all the aliases of a scoped object 
and statically raise an error if a reference escapes. This isn't 100% safe in a 
language that has all kind of casts and low-level features, but it's often safe 
enough, compared to other things. And those casts and low level features that 
can fool the escape analysis can be disabled statically (with something like 
@safe), this makes scoped classes 100% safe, probably safer than heap 
allocations.


The whole point of safe when talking about safe in D is memory saftey.

I know, but some people (including me) think that safe D is a misleading name 
because it just means memory safe D.


If the compiler can determine that a particular class object can be put on the 
stack and optimize it that way. Fine, but it's pretty rare that it can do that 
- essentially only in cases where you don't pass it to _anything_ except for 
pure functions (including calls to member functions).

I don't agree that it's rare. If a function that allocates an object calls a 
function (or member function) that's present in the same compilation unit (this 
more or less means same module), then the compiler is able to continue the 
escape analysis and determine if the called function escapes the reference. If 
this doesn't happen, then the class instance is free to be scoped. This 
situation is common enough.


And if the compiler can do that, then it there's no need for the programmer to 
use scope explicitly.

I don't agree. An annotation like @scope is a contract between the programmer 
and the compiler. It means that if the compiler sees a reference escape, then 
it stops the compilation.


And no, a compiler _can't_ do pure optimizations on its own, 
generally-speaking, because that would require looking not only at the body of 
the function that's being called but at the function bodies of any functions 
that it calls. D is not designed in a way that the compiler even necessarily 
has _access_ to a function's body when compiling, and you can't generally look 
at a function's body when doing optimizations when calling that function. So, 
_some_ pure optimizations could be done, but most couldn't. This is not the 
case with scoped classes, because purity already gives you the information 
that you need.

Quite often a function calls another function in thee same compilation unit, in 
this case the analysis is possible. So you limit the optimizations to this 
common but limited case.

And LDC compiler and in future GDC too, have link-time optimization, this means 
the compiler packs or sees the program code code in a single compilation unit. 
In this case it's able to perform a more complete analysis (including 
de-virtualization of some virtual functions).


Safety by convention means that the language and the compiler do not enforce 
it in any way.

This is not fully true. If the syntax of the unsafe thing is ugly and long, the 
programmer is discouraged to use it. This makes the unsafe thing more visible 
for the eyes of the programmer. Statistically this may reduce bug count.


There's nothing contradictory about Walter's stance. He's for having safety 
built into the language as much as reasonably possible and against having it 
thrust upon the programmer to program in a particular way to avoid unsafe 
stuff.

I think you have missed part of the context of my comments for Nick Voronin, he 
was trying to say something here:

Yet we won't have library solution for pointers instead of language support 
(hopefully)? :) I think it all goes against being practical as an objective 
of the language. Safety is important but you don't achieve safety by means of 
making unsafe thing unconvenient and inefficient. If there is emplace() then 
there is no reason not to have scope storage class. At least looking from 
user's POV. I don't know how hard it is on the compiler.
In _general_ case there is no safety in D. With all low-level capabilities one 
can always defeat compiler. Removing intermediate-level safer (yet unsafe) 
capabilities arguabily gains nothing but frustration. I'm all for encouraging 
good practices, but this is different.

In D the convention is to not use certain low-level means to do something (and 
@safe statically forbids them, so it's not just a 

Re: Classes or stucts :: Newbie

2010-12-20 Thread spir
On Mon, 20 Dec 2010 03:11:49 -0800
Jonathan M Davis jmdavisp...@gmx.com wrote:

 Now, you could conceivably have a language where all of its objects were 
 actually pointers, but they were treated as value types. So,
 
 B b;
 A a = b;
 
 would actually be declaring
 
 B* b;
 A* a = b;
 
 underneath the hood, except that the assignment would do a deep copy and 
 allocate the appropriate meemory rather than just copying the pointer like 
 would 
 happen in a language like C++ or D. Perhaps that's what Oberon does. I have 
 no 
 idea. I have never heard of the language before, let alone used it.

I don't know how Oberon works. But I'm sure that its records are plain values, 
_not_ pointed under the hood. And their methods all are virtual (they have a 
virtual method table). I have no more details, sorry.

Denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com



Re: Classes or stucts :: Newbie

2010-12-20 Thread Jonathan M Davis
On Monday, December 20, 2010 03:19:48 bearophile wrote:
 Jonathan M Davis:
  So, putting classes on the stack kind of negates the whole point of
  having both structs and classes in the first place.
 
 Where you put the instance is mostly a matter of implementation. This is
 why a smart JavaVM is able to perform escape analysis and choose where to
 allocate the class instance.
 
 Keep in mind that if you allocate a class on the stack or in-place inside
 another class, you don't turn it into a value, because beside the class
 instance you reserve space for its reference too (this reference may even
 be immutable, if you want).
 
  scoped classes are definitely not in SafeD.
 
 Well implemented scoped classes are safe enough (compared to the other
 things). The compiler may perform escape analysis of all the aliases of a
 scoped object and statically raise an error if a reference escapes. This
 isn't 100% safe in a language that has all kind of casts and low-level
 features, but it's often safe enough, compared to other things. And those
 casts and low level features that can fool the escape analysis can be
 disabled statically (with something like @safe), this makes scoped classes
 100% safe, probably safer than heap allocations.
 
 The whole point of safe when talking about safe in D is memory saftey.
 
 I know, but some people (including me) think that safe D is a misleading
 name because it just means memory safe D.

Talking about SafeD meaning memory safety makes the meaning of safety clear. If 
you try and make the term safety encompass more than that, it takes very little 
for safety to become subjective. Regardless of whether it would be nice if 
SafeD gave types of safety other than memory safety, when D documentation and 
any of the main D devs talk about safety, it is memory safety which is being 
referred to. Trying to expand the meaning beyond that will just cause confusion 
regardless of whether the non-memory safety being discussed is desirable or not.

 If the compiler can determine that a particular class object can be put on
 the stack and optimize it that way. Fine, but it's pretty rare that it
 can do that - essentially only in cases where you don't pass it to
 _anything_ except for pure functions (including calls to member
 functions).
 
 I don't agree that it's rare. If a function that allocates an object calls
 a function (or member function) that's present in the same compilation
 unit (this more or less means same module), then the compiler is able to
 continue the escape analysis and determine if the called function escapes
 the reference. If this doesn't happen, then the class instance is free to
 be scoped. This situation is common enough.
 
 And if the compiler can do that, then it there's no need for the
 programmer to use scope explicitly.
 
 I don't agree. An annotation like @scope is a contract between the
 programmer and the compiler. It means that if the compiler sees a
 reference escape, then it stops the compilation.
 
 And no, a compiler _can't_ do pure optimizations on its own,
 generally-speaking, because that would require looking not only at the
 body of the function that's being called but at the function bodies of
 any functions that it calls. D is not designed in a way that the compiler
 even necessarily has _access_ to a function's body when compiling, and
 you can't generally look at a function's body when doing optimizations
 when calling that function. So, _some_ pure optimizations could be done,
 but most couldn't. This is not the case with scoped classes, because
 purity already gives you the information that you need.
 
 Quite often a function calls another function in thee same compilation
 unit, in this case the analysis is possible. So you limit the
 optimizations to this common but limited case.
 
 And LDC compiler and in future GDC too, have link-time optimization, this
 means the compiler packs or sees the program code code in a single
 compilation unit. In this case it's able to perform a more complete
 analysis (including de-virtualization of some virtual functions).

It's trivial to get a reference or pointer to escape and make undetectable to 
the compiler. Some escape analysis can be and is done, but all it takes is 
passing a pointer or a reference to another function and the compiler can't 
determine it anymore unless it has access to the called functions body, and 
perhaps the bodies of functions that that function calls. And if the compiler 
can't be 100% correct with escape analysis, then any feature that requires it 
is 
not safe.

And as great as fancier optimizations such as link-time optimizations may be, 
the existence of dynamic libraries eliminates any and all guarantees that such 
optimizations would be able to make if they had all of the source to look at. 
So, you can't rely on them. They help, and they're great, but no feature can 
require them. They're optimizations only.

- Jonathan M Davis


Re: Classes or stucts :: Newbie

2010-12-20 Thread Jonathan M Davis
On Monday, December 20, 2010 06:24:56 spir wrote:
 On Mon, 20 Dec 2010 03:11:49 -0800
 
 Jonathan M Davis jmdavisp...@gmx.com wrote:
  Now, you could conceivably have a language where all of its objects were
  actually pointers, but they were treated as value types. So,
  
  B b;
  A a = b;
  
  would actually be declaring
  
  B* b;
  A* a = b;
  
  underneath the hood, except that the assignment would do a deep copy and
  allocate the appropriate meemory rather than just copying the pointer
  like would happen in a language like C++ or D. Perhaps that's what
  Oberon does. I have no idea. I have never heard of the language before,
  let alone used it.
 
 I don't know how Oberon works. But I'm sure that its records are plain
 values, _not_ pointed under the hood. And their methods all are virtual
 (they have a virtual method table). I have no more details, sorry.

Well, given C's memory model - which D uses - you can't do that. Oberon could 
use a different memory model and have some other way of doing it, but it won't 
work for D, so you'll never see structs with polymorphic behavior in D.

- Jonthan M Davis


Re: Classes or stucts :: Newbie

2010-12-20 Thread Steven Schveighoffer
On Sun, 19 Dec 2010 17:38:17 -0500, Jonathan M Davis jmdavisp...@gmx.com  
wrote:



On Sunday 19 December 2010 14:26:19 bearophile wrote:

Jonathan M Davis:
 There will be a library solution to do it, but again, it's unsafe.

It can be safer if the compiler gives some help. For me it's one of the
important unfinished parts of D.


Whereas, I would argue that it's completely unnecessary. structs and  
classes

serve different purposes. There is no need for scoped classes. They may
perodically be useful, but on the whole, they're completely unnecessary.

The compiler can help, but it can't fix the problem any more that it can
guarantee that a pointer to a local variable doesn't escape once you've  
passed
it to another function. In _some_ circumstances, it can catch escaping  
pointers

and references, but in the general case, it can't.

If we have library solutions for people who want to play with fire,  
that's fine.
But scoped classes is just not one of those things that the language  
really

needs. They complicate things unnecessarily for minimal benefit.


I don't mind having a solution as long as there is a solution.

The main need I see for scoped classes is for when you *know* as the  
programmer that the lifetime of a class or struct will not exceed the  
lifetime of a function, but you don't want to incur the penalty of  
allocating on the heap.  Mostly this is because the functions you want to  
call take classes or interfaces.


It's difficult to find an example with Phobos since there are not many  
classes.  But with Tango, scoped classes are used everywhere.


-Steve


Re: Classes or stucts :: Newbie

2010-12-20 Thread Nick Voronin
On Mon, 20 Dec 2010 05:43:08 -0500
bearophile bearophileh...@lycos.com wrote:

 Nick Voronin:
 
  Here is where we diverge. Choosing struct vs class on criteria of their 
  placement makes no sense to me. 
 
 In D you use a class if you want inheritance or when you (often) need 
 reference semantics, and you use a struct when you need a little value passed 
 around by value or when you want a simple form of RAII or when you want to 
 implement something manually (like using PIMPL), or when you want max 
 performance (and you manage structs by pointer, you may even put a tag inside 
 the stuct or the pointer and implement manually some kind of inheritance). 
 With structs you have a literal syntax, postblits, in-place allocation, and 
 you are free to use align() too.

Well said. Plenty of differences there more important than stack/heap 
allocation.

-- 
Nick Voronin elfy...@gmail.com


Classes or stucts :: Newbie

2010-12-19 Thread David Currie

I am new to D (like many have done C++ , Java ).

Can a class be instantiated on the stack ?

eg

class C
{
  private  int _I1;
  private  int _I2;

  public:

  this(int pI) // constructor
  {
_I1 = pI;
_I2 = pI + 1;
  }

// ...  other methods etc
}

void f()  // just a function
{

  C myC(3);  // C++ syntax BUT is there a d equivalent

}

It appears that D ASSUMES myC is really a myC*(in C++)

and therefore requires

C myC = new C(3);
// but this ALWAYS requires calling the memory allocator
// this is what Java does (forces your Class instance onto the Heap)

Is there any way in D to instantiate a stack object ?

Will a struct do?

Does a struct have a constructor (as opposed to an opcall?)

I would be very grateful for a response.

David Currie




Re: Classes or stucts :: Newbie

2010-12-19 Thread Denis Koroskin
On Mon, 20 Dec 2010 18:00:31 +0300, David Currie curri...@iinet.net.au  
wrote:



I am new to D (like many have done C++ , Java ).

Can a class be instantiated on the stack ?

eg

class C
{
   private  int _I1;
   private  int _I2;

   public:

   this(int pI) // constructor
   {
 _I1 = pI;
 _I2 = pI + 1;
   }

// ...  other methods etc
}

void f()  // just a function
{

   C myC(3);  // C++ syntax BUT is there a d equivalent

}

It appears that D ASSUMES myC is really a myC*(in C++)

and therefore requires

C myC = new C(3);
// but this ALWAYS requires calling the memory allocator
// this is what Java does (forces your Class instance onto the Heap)

Is there any way in D to instantiate a stack object ?

Will a struct do?

Does a struct have a constructor (as opposed to an opcall?)

I would be very grateful for a response.

David Currie




Try the following:

scope c = new C(3);

Unfortunately last I've heard it's going to be deprecated in favor of a  
library solution:


InSitu!(C) c = InSitu!(C)(3); // IIRC not implemented yet


Re: Classes or stucts :: Newbie

2010-12-19 Thread Denis Koroskin
On Mon, 20 Dec 2010 18:00:31 +0300, David Currie curri...@iinet.net.au  
wrote:



I am new to D (like many have done C++ , Java ).

Can a class be instantiated on the stack ?

eg

class C
{
   private  int _I1;
   private  int _I2;

   public:

   this(int pI) // constructor
   {
 _I1 = pI;
 _I2 = pI + 1;
   }

// ...  other methods etc
}

void f()  // just a function
{

   C myC(3);  // C++ syntax BUT is there a d equivalent

}

It appears that D ASSUMES myC is really a myC*(in C++)

and therefore requires

C myC = new C(3);
// but this ALWAYS requires calling the memory allocator
// this is what Java does (forces your Class instance onto the Heap)

Is there any way in D to instantiate a stack object ?

Will a struct do?

Does a struct have a constructor (as opposed to an opcall?)

I would be very grateful for a response.

David Currie




To your second question, yes, structs would do:

struct C
{
this(int i) { ... }
}

C c = C(3);


Re: Classes or stucts :: Newbie

2010-12-19 Thread bearophile
David Currie:

 I am new to D (like many have done C++ , Java ).

Welcome to D :-)
What language do you refer to, D1 or D2? The answers here are about the latest 
versions of D2.


 Can a class be instantiated on the stack ?

There was a way built in the language to do that (using scope, it works still 
but it's deprecated), but now you have to use the std library. See the 
std.conv.emplace, but keep in mind it has issues (more than the issues of 
scope!) like I think not calling the object destructor.


 It appears that D ASSUMES myC is really a myC*(in C++)

Right, in D class instances are always managed by reference, even when you 
allocate them on the stack using the emplace trick.


 // but this ALWAYS requires calling the memory allocator
 // this is what Java does (forces your Class instance onto the Heap)

A difference is that the Oracle Java Garbage Collector has a Eden memory for 
the newly allocated objects that's much faster than the current D GC :-)


 Will a struct do?

Sometimes a struct is enough. D structs are managed by value or by pointer, but 
they don't support inheritance. In D structs and classes are different (like 
the memory layout of a class instance is decided by the compiler, while struct 
fields are in memory as you want them, with the alignment you desire) and they 
are used for different purposes.


 Does a struct have a constructor (as opposed to an opcall?)

In D2 the struct constructor is this() as for classes.

Bye,
bearophile


Re: Classes or stucts :: Newbie

2010-12-19 Thread bearophile
Denis Koroskin:

 Unfortunately last I've heard it's going to be deprecated in favor of a  
 library solution:
 
 InSitu!(C) c = InSitu!(C)(3); // IIRC not implemented yet

It's named scoped, see about its problems:
http://d.puremagic.com/issues/show_bug.cgi?id=5115

Bye,
bearophile


Re: Classes or stucts :: Newbie

2010-12-19 Thread Joost 't Hart

On 12/20/2010 04:00 PM, David Currie wrote:


I am new to D (like many have done C++ , Java ).


Me too. Let's see what we can figure out together :-)



Can a class be instantiated on the stack ?

eg

class C
{
private int _I1;
private int _I2;

public:

this(int pI) // constructor
{
_I1 = pI;
_I2 = pI + 1;
}

// ... other methods etc
}

void f() // just a function
{

C myC(3); // C++ syntax BUT is there a d equivalent

}

It appears that D ASSUMES myC is really a myC*(in C++)


It is not so much a *, but reference semantics (like T param in C++).



and therefore requires

C myC = new C(3);
// but this ALWAYS requires calling the memory allocator
// this is what Java does (forces your Class instance onto the Heap)

Is there any way in D to instantiate a stack object ?


Not a class object. Only values are on the stack. The reference 
semantics requires a living entity to refer to.




Will a struct do?


Yes, if you so wish, but new also works. Structs have value semantics.



Does a struct have a constructor (as opposed to an opcall?)


You can define one, but you cannot redefine the default this() 
constructor. Because structs have value semantics, D wants to make sure 
that T.init member values are slotted in by default. Note that T.init 
for a class type is the null reference.




I would be very grateful for a response.


Hope this helps a bit.
Cheers,
Joost.



David Currie






Re: Classes or stucts :: Newbie

2010-12-19 Thread bearophile
 See the std.conv.emplace, 

Sorry, see std.typecons.scoped and its problems:
http://d.puremagic.com/issues/show_bug.cgi?id=5115

Bye,
bearophile


Re: Classes or stucts :: Newbie

2010-12-19 Thread Andrej Mitrovic
There's also scoped() in std.typecons, but I think this will still
allocate on the heap. Not sure..

On 12/19/10, bearophile bearophileh...@lycos.com wrote:
 David Currie:

 I am new to D (like many have done C++ , Java ).

 Welcome to D :-)
 What language do you refer to, D1 or D2? The answers here are about the
 latest versions of D2.


 Can a class be instantiated on the stack ?

 There was a way built in the language to do that (using scope, it works
 still but it's deprecated), but now you have to use the std library. See the
 std.conv.emplace, but keep in mind it has issues (more than the issues of
 scope!) like I think not calling the object destructor.


 It appears that D ASSUMES myC is really a myC*(in C++)

 Right, in D class instances are always managed by reference, even when you
 allocate them on the stack using the emplace trick.


 // but this ALWAYS requires calling the memory allocator
 // this is what Java does (forces your Class instance onto the Heap)

 A difference is that the Oracle Java Garbage Collector has a Eden memory for
 the newly allocated objects that's much faster than the current D GC :-)


 Will a struct do?

 Sometimes a struct is enough. D structs are managed by value or by pointer,
 but they don't support inheritance. In D structs and classes are different
 (like the memory layout of a class instance is decided by the compiler,
 while struct fields are in memory as you want them, with the alignment you
 desire) and they are used for different purposes.


 Does a struct have a constructor (as opposed to an opcall?)

 In D2 the struct constructor is this() as for classes.

 Bye,
 bearophile



Re: Classes or stucts :: Newbie

2010-12-19 Thread Andrej Mitrovic
On 12/19/10, bearophile bearophileh...@lycos.com wrote:
 See the std.conv.emplace,

 Sorry, see std.typecons.scoped and its problems:
 http://d.puremagic.com/issues/show_bug.cgi?id=5115

 Bye,
 bearophile


Is this another bug?:

import std.stdio;
import std.typecons;

class A
{
~this()
{
writeln(dtor);
}
}

void main()
{
{
A a1 = scoped!A();   // doesn't call dtor after the scope
auto a2 = scoped!A();  // calls dtor after the scope
}
}


Re: Classes or stucts :: Newbie

2010-12-19 Thread bearophile
Andrej Mitrovic:

 There's also scoped() in std.typecons, but I think this will still
 allocate on the heap. Not sure..

It allocates on the stack.

Bye,
bearophile


Re: Classes or stucts :: Newbie

2010-12-19 Thread bearophile
Andrej Mitrovic:

 Is this another bug?:

I don't exactly know what's going on, but I have added a modified version of 
your code to the issue 5115.

Bye,
bearophile


Re: Classes or stucts :: Newbie

2010-12-19 Thread Nick Voronin
On Mon, 20 Dec 2010 07:00:31 -0800
David Currie curri...@iinet.net.au wrote:

 Can a class be instantiated on the stack ?

Yes, check std.conv.emplace 
http://www.digitalmars.com/d/2.0/phobos/std_conv.html#emplace and alloca()
I don't know details about interaction of such objects with GC though.

Also there is scarcely documented storage class scope, which for class objects 
means that they will be destroyed upon scope exit, but also currently results 
in that object itself will be placed on the stack, no memory in heap is 
allocated.

C myC(3);  // C++ syntax BUT is there a d equivalent
 It appears that D ASSUMES myC is really a myC*(in C++)

Not exactly. All class objects have reference semantic, so when you declare 
variable of type C you really declare a reference. The reference is what you 
get from new, pass as parameters, etc.

 Will a struct do?

structs on the contrary have value semantic, so when you declare struct 
variable you get the memory for struct allocated on stack or in data segment. 
When you pass or return structs -- you return or pass value, that is a copy of 
data.

You may be also interested in the way dynamic arrays are handled, as arrays are 
value type, yet they hold a pointer to memory. This means that passing them as 
parameter or returning them does copy pointer and length, but actual data is 
stil shared until you do something which will force D to relocate it. All kind 
of not obvious implications here.

 Does a struct have a constructor (as opposed to an opcall?)

Yes, and more. http://www.digitalmars.com/d/2.0/struct.html

-- 
Nick Voronin elfy...@gmail.com


Re: Classes or stucts :: Newbie

2010-12-19 Thread Jonathan M Davis
On Monday 20 December 2010 07:00:31 David Currie wrote:
 I am new to D (like many have done C++ , Java ).
 
 Can a class be instantiated on the stack ?
 
 eg
 
 class C
 {
private  int _I1;
private  int _I2;
 
public:
 
this(int pI) // constructor
{
  _I1 = pI;
  _I2 = pI + 1;
}
 
 // ...  other methods etc
 }
 
 void f()  // just a function
 {
 
C myC(3);  // C++ syntax BUT is there a d equivalent
 
 }
 
 It appears that D ASSUMES myC is really a myC*(in C++)
 
 and therefore requires
 
 C myC = new C(3);
 // but this ALWAYS requires calling the memory allocator
 // this is what Java does (forces your Class instance onto the Heap)
 
 Is there any way in D to instantiate a stack object ?
 
 Will a struct do?

Structs are value types. Therefore, they go on the stack unless you have a 
pointer to them.

struct Foo {}

Foo a;  //on stack
Foo* b = new Foo(); //on heap


Classes are reference types. The are therefore always on the heap. It's like 
what you get in Java.

class Bar {}

Bar a;  //On the heap.


Structs do not have inheritance (and thus don't have polymorphism), but they 
can 
be used for RAII. Assigning one to another means copying it (or moving it if 
the 
compiler determines that it can). Because struct member functions are not 
virtual, they often can be inlined.

Classes do have inheritance (and thus do have polymorphism), but they can't use 
RAII. Assigning one to another means assigning a reference. Both references now 
refer to the same object. You'll have to use a clone method of some kind to get 
an actualy, deep copy. Because class member functions are almost always 
virtual, 
it's much rarer that they can be inlined.

The language did have scoped classes, which put the class itself on the stack 
instead of the heap:

class Bar {}

scope Bar a; //On the stack.


But it's inherently unsafe, so it's being removed from the language. There will 
be a library solution to do it, but again, it's unsafe. If you were to pass a 
scaped class to any other function, you risk the reference escaping, and then 
you'll end up with a reference to an object that doesn't exist once the 
function 
that declared it exits.

Classes are meant to be on the heap. structs are meant to be on the stack but 
can be on the heap. Generally-speaking, if you use a class if you need a 
reference type or need polymorphism. Otherwise, you use a struct (reasons for 
using one or the other can, of course, get more complicated that that, but 
that's the core of it).

Allowing classes on the like C++ does allows for problems like sheering and 
disallows polymorphism. D opted to split the concept into two different types 
of 
types: classes and structs.

The language which is closest to D with regards to structs and classes that I'm 
aware of is C#, though I believe that D structs are definitely more powerful 
than 
C# structs. In D, you just don't use classes as often as you'd do in Java or 
C++, because structs in D do a lot of what classes do in those languages. For 
any user-defined type, you need to decide whether a struct or a class is more 
appropriate for what you're trying to do. The approach has definite benefits, 
but 
it does take some getting used to.

 Does a struct have a constructor (as opposed to an opcall?)

structs can have constructs just like classes - they just can't have default 
constructors. The reason for this is that all types in D have an init property 
that variables of that type are initialized to when they are default 
initialized. For integral types, it's 0; for bool, it's false; for references 
and pointers it's null; etc. For structs, it's what the member variables are 
directly initialized to. init precludes having an arbitrary constructor, 
because 
init must be determinable at compile time, can't have exceptions being thrown, 
etc. We may get some sort of limited default constructor for structs at some 
point, but it's not at all straightforward to have one, so we don't. The 
solution then, if you need one, is to use a static opCall() function, and then 
do

Foo a = Foo(); //calls static opCall().

instead of

Foo a;  //Just uses Foo.init.


So, structs _do_ have constructors, just not default constructors.

- Jonathan M Davis


Re: Classes or stucts :: Newbie

2010-12-19 Thread bearophile
Jonathan M Davis:

 There will be a library solution to do it, but again, it's unsafe.

It can be safer if the compiler gives some help. For me it's one of the 
important unfinished parts of D.

Bye,
bearophile


Re: Classes or stucts :: Newbie

2010-12-19 Thread Jonathan M Davis
On Sunday 19 December 2010 13:23:42 Jonathan M Davis wrote:
 On Monday 20 December 2010 07:00:31 David Currie wrote:
  I am new to D (like many have done C++ , Java ).
  
  Can a class be instantiated on the stack ?
  
  eg
  
  class C
  {
  
 private  int _I1;
 private  int _I2;
 
 public:
 
 this(int pI) // constructor
 {
 
   _I1 = pI;
   _I2 = pI + 1;
 
 }
  
  // ...  other methods etc
  }
  
  void f()  // just a function
  {
  
 C myC(3);  // C++ syntax BUT is there a d equivalent
  
  }
  
  It appears that D ASSUMES myC is really a myC*(in C++)
  
  and therefore requires
  
  C myC = new C(3);
  // but this ALWAYS requires calling the memory allocator
  // this is what Java does (forces your Class instance onto the Heap)
  
  Is there any way in D to instantiate a stack object ?
  
  Will a struct do?
 
 Structs are value types. Therefore, they go on the stack unless you have a
 pointer to them.
 
 struct Foo {}
 
 Foo a;  //on stack
 Foo* b = new Foo(); //on heap
 
 
 Classes are reference types. The are therefore always on the heap. It's
 like what you get in Java.
 
 class Bar {}
 
 Bar a;  //On the heap.
 
 
 Structs do not have inheritance (and thus don't have polymorphism), but
 they can be used for RAII. Assigning one to another means copying it (or
 moving it if the compiler determines that it can). Because struct member
 functions are not virtual, they often can be inlined.
 
 Classes do have inheritance (and thus do have polymorphism), but they can't
 use RAII. Assigning one to another means assigning a reference. Both
 references now refer to the same object. You'll have to use a clone method
 of some kind to get an actualy, deep copy. Because class member functions
 are almost always virtual, it's much rarer that they can be inlined.
 
 The language did have scoped classes, which put the class itself on the
 stack instead of the heap:
 
 class Bar {}
 
 scope Bar a; //On the stack.
 
 
 But it's inherently unsafe, so it's being removed from the language. There
 will be a library solution to do it, but again, it's unsafe. If you were
 to pass a scaped class to any other function, you risk the reference
 escaping, and then you'll end up with a reference to an object that
 doesn't exist once the function that declared it exits.
 
 Classes are meant to be on the heap. structs are meant to be on the stack
 but can be on the heap. Generally-speaking, if you use a class if you need
 a reference type or need polymorphism. Otherwise, you use a struct
 (reasons for using one or the other can, of course, get more complicated
 that that, but that's the core of it).
 
 Allowing classes on the like C++ does allows for problems like sheering and
 disallows polymorphism. D opted to split the concept into two different
 types of types: classes and structs.
 
 The language which is closest to D with regards to structs and classes that
 I'm aware of is C#, though I believe that D structs are definitely more
 powerful than C# structs. In D, you just don't use classes as often as
 you'd do in Java or C++, because structs in D do a lot of what classes do
 in those languages. For any user-defined type, you need to decide whether
 a struct or a class is more appropriate for what you're trying to do. The
 approach has definite benefits, but it does take some getting used to.
 
  Does a struct have a constructor (as opposed to an opcall?)
 
 structs can have constructs just like classes - they just can't have
 default constructors. The reason for this is that all types in D have an
 init property that variables of that type are initialized to when they are
 default initialized. For integral types, it's 0; for bool, it's false; for
 references and pointers it's null; etc. For structs, it's what the member
 variables are directly initialized to. init precludes having an arbitrary
 constructor, because init must be determinable at compile time, can't have
 exceptions being thrown, etc. We may get some sort of limited default
 constructor for structs at some point, but it's not at all straightforward
 to have one, so we don't. The solution then, if you need one, is to use a
 static opCall() function, and then do
 
 Foo a = Foo(); //calls static opCall().
 
 instead of
 
 Foo a;  //Just uses Foo.init.
 
 
 So, structs _do_ have constructors, just not default constructors.

I should probably add that structs can have reference semantics as well if they 
have pointers or references internally, and they don't have a postblit 
constructor or, it doesn't do a deep copy (a postblit constructor - this(this) 
- 
being the constructor which runs after a struct has been memcpy-ed by the 
compiler, since the default copying of a struct uses memcpy). structs are 
generally value types, however, and classes are always reference types.

- Jonathan M Davis


Re: Classes or stucts :: Newbie

2010-12-19 Thread Jonathan M Davis
On Sunday 19 December 2010 14:26:19 bearophile wrote:
 Jonathan M Davis:
  There will be a library solution to do it, but again, it's unsafe.
 
 It can be safer if the compiler gives some help. For me it's one of the
 important unfinished parts of D.

Whereas, I would argue that it's completely unnecessary. structs and classes 
serve different purposes. There is no need for scoped classes. They may 
perodically be useful, but on the whole, they're completely unnecessary.

The compiler can help, but it can't fix the problem any more that it can 
guarantee that a pointer to a local variable doesn't escape once you've passed 
it to another function. In _some_ circumstances, it can catch escaping pointers 
and references, but in the general case, it can't.

If we have library solutions for people who want to play with fire, that's 
fine. 
But scoped classes is just not one of those things that the language really 
needs. They complicate things unnecessarily for minimal benefit.

- Jonathan M Davis


Re: Classes or stucts :: Newbie

2010-12-19 Thread Nick Voronin
On Sun, 19 Dec 2010 14:38:17 -0800
Jonathan M Davis jmdavisp...@gmx.com wrote:

 On Sunday 19 December 2010 14:26:19 bearophile wrote:
  Jonathan M Davis:
   There will be a library solution to do it, but again, it's unsafe.
  
  It can be safer if the compiler gives some help. For me it's one of the
  important unfinished parts of D.
 
 Whereas, I would argue that it's completely unnecessary. structs and classes 
 serve different purposes. There is no need for scoped classes. They may 
 perodically be useful, but on the whole, they're completely unnecessary.

How do you define a need for scoped classes? 

I see two aspects there: first is having destructor called at known point 
rather than arbitrarily, second is performance.

It looks perfectly reasonable for me to want to have first. Do you know why 
things which makes program act more deterministic are shunned from D? Does it 
really add so much to safety that it is worth reducing programmer's control?

Second is irrelevant to types, if I want to speed up some code and can do it by 
placing things on stack rather than in heap -- what does it matter if it is 
class or struct or integer? We have alloca() anyway, so removing modifier won't 
save me from myself, just push me to more C-like code. Which kind of defeats 
the purpose of using D.

 The compiler can help, but it can't fix the problem any more that it can 
 guarantee that a pointer to a local variable doesn't escape once you've 
 passed 
 it to another function.

Absolutely. Yet we won't have library solution for pointers instead of language 
support (hopefully)? :) I think it all goes against being practical as an 
objective of the language. Safety is important but you don't achieve safety by 
means of making unsafe thing unconvenient and inefficient. If there is 
emplace() then there is no reason not to have scope storage class. At least 
looking from user's POV. I don't know how hard it is on the compiler.

 In _some_ circumstances, it can catch escaping pointers 
 and references, but in the general case, it can't.

In _general_ case there is no safety in D. With all low-level capabilities one 
can always defeat compiler. Removing intermediate-level safer (yet unsafe) 
capabilities arguabily gains nothing but frustration. I'm all for encouraging 
good practices, but this is different.

-- 
Nick Voronin elfy...@gmail.com


Re: Classes or stucts :: Newbie

2010-12-19 Thread Andrej Mitrovic
On 12/20/10, Nick Voronin elfy...@gmail.com wrote:
 I see two aspects there: first is having destructor called at known point
 rather than arbitrarily, second is performance.


There's still an alternative for the first part, scope(exit):

import std.stdio;

class A
{
~this()
{
writeln(A.dtor);
}
void test()
{
writeln(test);
}
}

void main()
{
A a = new A();
scope(exit)
{
clear(a);
}
a.test();
}

 test
 A.dtor
 A.dtor


Re: Classes or stucts :: Newbie

2010-12-19 Thread Jonathan M Davis
On Sunday 19 December 2010 16:50:34 Nick Voronin wrote:
 On Sun, 19 Dec 2010 14:38:17 -0800
 
 Jonathan M Davis jmdavisp...@gmx.com wrote:
  On Sunday 19 December 2010 14:26:19 bearophile wrote:
   Jonathan M Davis:
There will be a library solution to do it, but again, it's unsafe.
   
   It can be safer if the compiler gives some help. For me it's one of the
   important unfinished parts of D.
  
  Whereas, I would argue that it's completely unnecessary. structs and
  classes serve different purposes. There is no need for scoped classes.
  They may perodically be useful, but on the whole, they're completely
  unnecessary.
 
 How do you define a need for scoped classes?
 
 I see two aspects there: first is having destructor called at known point
 rather than arbitrarily, second is performance.
 
 It looks perfectly reasonable for me to want to have first. Do you know why
 things which makes program act more deterministic are shunned from D? Does
 it really add so much to safety that it is worth reducing programmer's
 control?

Then use a struct. That's one of the reasons that they exist. And if you 
_really_ want to make sure that a class' destructor gets run, you can always 
use 
clear() (which is arguably an abomination in its own right). And if you use 
that 
in combination with scope(exit), then you get a class which is guaranteed to be 
destroyed when the function exits, and (assuming that clear() is fully 
implemented and actually zeroes out the vtable - which I don't think that it 
does yet), you won't be using garbage memory (though obviously it will still go 
boom - likely due to a segfault).

Part of the whole point of separating classes and structs is to separate the 
issue of where they go - on the stack or on the heap. So, putting classes on 
the 
stack kind of negates the whole point of having both structs and classes in the 
first place.

 In _general_ case there is no safety in D. With all low-level capabilities
 one can always defeat compiler. Removing intermediate-level safer (yet
 unsafe) capabilities arguabily gains nothing but frustration. I'm all for
 encouraging good practices, but this is different.

In the general case when using SafeD, there D _is_ safe. scoped classes are 
definitely not in SafeD.

structs already are on the stack. If you want something on the stack, then use 
structs. And if you _really_ want a class on the stack for whatever reason 
(which I _really_ question), then there will be a library solution to the 
problem. By putting classes on the stack, you're pretty much ignoring the 
differences between structs and classes.

- Jonathan M Davis


Re: Classes or stucts :: Newbie

2010-12-19 Thread Nick Voronin
On Sun, 19 Dec 2010 17:26:20 -0800
Jonathan M Davis jmdavisp...@gmx.com wrote:

 On Sunday 19 December 2010 16:50:34 Nick Voronin wrote:
  On Sun, 19 Dec 2010 14:38:17 -0800
  
  Jonathan M Davis jmdavisp...@gmx.com wrote:
   On Sunday 19 December 2010 14:26:19 bearophile wrote:
Jonathan M Davis:
 There will be a library solution to do it, but again, it's unsafe.

It can be safer if the compiler gives some help. For me it's one of the
important unfinished parts of D.
   
   Whereas, I would argue that it's completely unnecessary. structs and
   classes serve different purposes. There is no need for scoped classes.
   They may perodically be useful, but on the whole, they're completely
   unnecessary.
  
  How do you define a need for scoped classes?
  
  I see two aspects there: first is having destructor called at known point
  rather than arbitrarily, second is performance.
  
  It looks perfectly reasonable for me to want to have first. Do you know why
  things which makes program act more deterministic are shunned from D? Does
  it really add so much to safety that it is worth reducing programmer's
  control?
 
 Then use a struct.

Here is where we diverge. Choosing struct vs class on criteria of their 
placement makes no sense to me. Difference in default placement hardly matters 
at all, you can perfectly put structs in heap or in static segment yet still 
maintain same properties. It's those properties which matter when I choose one 
or another, not where it will reside in particular part of program.

 That's one of the reasons that they exist. And if you 
 _really_ want to make sure that a class' destructor gets run, you can always 
 use 
 clear() (which is arguably an abomination in its own right).

This is what I don't understand. Fine. structs are meant for stack, class for 
heap. Conceptually, anyway. Still there will be ways to put class on stack and 
struct in heap. And there is(will be) clear(). Now I do see benefit of scope 
storage. It looks clean, it is supported by compiler meaning reasonable level 
of protection against misuse, it is extremely effective. What are benefits of 
_not having_ it?

-- 
Nick Voronin elfy...@gmail.com


Re: Classes or stucts :: Newbie

2010-12-19 Thread Jonathan M Davis
On Sunday 19 December 2010 18:13:54 Nick Voronin wrote:
 On Sun, 19 Dec 2010 17:26:20 -0800
 
 Jonathan M Davis jmdavisp...@gmx.com wrote:
  On Sunday 19 December 2010 16:50:34 Nick Voronin wrote:
   On Sun, 19 Dec 2010 14:38:17 -0800
   
   Jonathan M Davis jmdavisp...@gmx.com wrote:
On Sunday 19 December 2010 14:26:19 bearophile wrote:
 Jonathan M Davis:
  There will be a library solution to do it, but again, it's
  unsafe.
 
 It can be safer if the compiler gives some help. For me it's one of
 the important unfinished parts of D.

Whereas, I would argue that it's completely unnecessary. structs and
classes serve different purposes. There is no need for scoped
classes. They may perodically be useful, but on the whole, they're
completely unnecessary.
   
   How do you define a need for scoped classes?
   
   I see two aspects there: first is having destructor called at known
   point rather than arbitrarily, second is performance.
   
   It looks perfectly reasonable for me to want to have first. Do you know
   why things which makes program act more deterministic are shunned from
   D? Does it really add so much to safety that it is worth reducing
   programmer's control?
  
  Then use a struct.
 
 Here is where we diverge. Choosing struct vs class on criteria of their
 placement makes no sense to me. Difference in default placement hardly
 matters at all, you can perfectly put structs in heap or in static segment
 yet still maintain same properties. It's those properties which matter
 when I choose one or another, not where it will reside in particular part
 of program.
 
  That's one of the reasons that they exist. And if you
  _really_ want to make sure that a class' destructor gets run, you can
  always use clear() (which is arguably an abomination in its own right).
 
 This is what I don't understand. Fine. structs are meant for stack, class
 for heap. Conceptually, anyway. Still there will be ways to put class on
 stack and struct in heap. And there is(will be) clear(). Now I do see
 benefit of scope storage. It looks clean, it is supported by compiler
 meaning reasonable level of protection against misuse, it is extremely
 effective. What are benefits of _not having_ it?

Except that the compiler _can't_ protect against misuse. That's one of the main 
reasons that it's going away as part of the language. Structs are intended to 
their lifetime be the same as their scope. The lifetime for classes, on the 
other hand, is essentially as long as the program is running (though the 
garbage 
collector can obviously collect them in cases where they aren't used anymore). 
By trying to force a reference type to have a scoped lifetime, you're going 
against how they work, and it's just asking for trouble. Yes, it _can_ be done, 
but no, it _can't_ be done safely.

As I understand it, Andrei isn't even entirely happy that clear() exists. I 
believe that pretty much the only reason that it exists is because there are 
cases where classes hold resources and you want to make sure that they get 
released rather than waiting for the object to get destroyed at some 
indeterminate point in the future. But really, the garbage collected heap is 
supposed to be managed by the garbage collector. And with scope, you're trying 
to take something that's designed to live on the garbage collected heap and put 
it on the stack. You're taking something that is designed to be used in one 
type 
of storage and using it in another. It's going to cause problems.

C++ has a number of issues pricely because it allows classes to live on both 
the 
stack and the heap. By separating types that live on the stack from those that 
live on the heap, you avoid those problems.

And actually, the fact that structs can live in the heap in D can be 
problematic, as evidenced by the bugs relating to destructors for structs on 
the 
heap. Not only do their destructors not get run, it's questionable whether the 
language will _ever_ be such that the destructors of structs on the heap will 
be 
run. The result is that in many cases, structs should either be designed to be 
on the stack or on the heap.

D was designed so that classes live on the heap, and that's the way it works. 
Putting them on the stack is going against how classes are intended to work, 
and 
it's asking for trouble.

- Jonathan M Davis


Re: Classes or stucts :: Newbie

2010-12-19 Thread bearophile
Jonathan M Davis:

 Whereas, I would argue that it's completely unnecessary.

Recently even the Oracle Java VM allocates some class instances on the stack, 
when Escape Analysis finds it's safe to do so. And D lacks the very efficient 
GC of the JVM, so for D it's even more important to use the stack for some 
classes.

Think about the pure tag of D2. 

D1 lacks the pure annotation, but an advanced D1 compiler may add some logic 
able to tell if a function is pure, and use this info for performance purposes. 
The problem here is that if you change the function a little your function may 
stop being pure and the optimization becomes impossible. The pure annotation 
of D2 is a contract between the programmer and the compiler. In the same way, 
even if a D compiler gains an automatic escape analysis like Java and a much 
more efficient GC, a way to annotate a class as scoped is useful still, because 
like pure it's a contract between the compiler and the programmer, it 
enforces that a class instance doesn't escape a scope (if you try to escape it, 
the good compiler in most cases gives an error. While in this case the JVM just 
doesn't allocate the object on the stack), this also means guaranteed 
performance and deallocation determinism.

Another thing to keep in account is that we aren't talking just about the 
stack, but generally about in-place allocation. So if you have a class instance 
A, one of its fields may be another class instance B, that's scoped. Here B is 
allocated on the heap, because B is contained inside A, that is (generally) on 
the heap. Yet B is allocated in-place. Having a single heap allocation instead 
of two when you create an instance A is a significant performance gain (and I 
think Java doesn't perform this optimization yet). A well designed type system 
is then able to make all this safe.


 The compiler can help, but it can't fix the problem any more that it can 
 guarantee that a pointer to a local variable doesn't escape once you've 
 passed 
 it to another function. In _some_ circumstances, it can catch escaping 
 pointers 
 and references, but in the general case, it can't.

See also: http://en.wikipedia.org/wiki/Linear_types
Stronger and more powerful type systems are possible (D has means to break any 
type system, but the programmer does this knowing what she or he is doing. And 
there are ways similar to @safe to statically disallow the means you may use to 
break this part of the type system).


So, putting classes on the stack kind of negates the whole point of having 
both structs and classes in the first place.

This is false, the definition of D class instance doesn't specify where the 
instance memory is allocated.


In the general case when using SafeD, there D _is_ safe. scoped classes are 
definitely not in SafeD.

SafeD is not safe. It allows integer overflows, memory overflows, etc. SafeD 
just disallows a certain (important) kind of memory bugs. This is why some 
people have asked to call it memory safe.

If you take a look at coding standards that specify how to write high integrity 
software (MISRA-C, SPARK, Joint Strike Fighter Air Vehicle C++ Coding 
Standards, etc), you will see that they forbid ALL heap allocations, because 
stack allocations are more deterministic and more predictable, so they are 
safer. If you disallow recursion the max required size of the stack is even 
computable statically, avoiding stack overflows.

-

Nick Voronin:

Safety is important but you don't achieve safety by means of making unsafe 
thing unconvenient and inefficient.

I know that sounds a little weird, but in practice this is how some parts of D 
are designed :-)
Yet, Walter has said many things that he doesn't like safety by convention. 
So I presume there is some contradiction here :-)

A language like Cyclone has tried to make low-level operations in a very 
C-language safe, and it succeeds in this, but Cyclone is both slow, fussy, not 
handy, a failure. So by design D doesn't try to make low-level operation safe, 
it just add safe(r) hi-level operations. You are allowed to use the low-level 
means still, but in this case you are fully on your own, like in C. For a lot 
of time I have not appreciated much this basic design decision, but so far it 
has worked well enough, far better than Cyclone.

Bye,
bearophile


Re: Classes or stucts :: Newbie

2010-12-19 Thread Jonathan M Davis
On Sunday 19 December 2010 18:33:56 bearophile wrote:
 Jonathan M Davis:
  Whereas, I would argue that it's completely unnecessary.
 
 Recently even the Oracle Java VM allocates some class instances on the
 stack, when Escape Analysis finds it's safe to do so. And D lacks the very
 efficient GC of the JVM, so for D it's even more important to use the
 stack for some classes.
 
 Think about the pure tag of D2.
 
 D1 lacks the pure annotation, but an advanced D1 compiler may add some
 logic able to tell if a function is pure, and use this info for
 performance purposes. The problem here is that if you change the function
 a little your function may stop being pure and the optimization becomes
 impossible. The pure annotation of D2 is a contract between the
 programmer and the compiler. In the same way, even if a D compiler gains
 an automatic escape analysis like Java and a much more efficient GC, a way
 to annotate a class as scoped is useful still, because like pure it's a
 contract between the compiler and the programmer, it enforces that a class
 instance doesn't escape a scope (if you try to escape it, the good
 compiler in most cases gives an error. While in this case the JVM just
 doesn't allocate the object on the stack), this also means guaranteed
 performance and deallocation determinism.
 
 Another thing to keep in account is that we aren't talking just about the
 stack, but generally about in-place allocation. So if you have a class
 instance A, one of its fields may be another class instance B, that's
 scoped. Here B is allocated on the heap, because B is contained inside A,
 that is (generally) on the heap. Yet B is allocated in-place. Having a
 single heap allocation instead of two when you create an instance A is a
 significant performance gain (and I think Java doesn't perform this
 optimization yet). A well designed type system is then able to make all
 this safe.
 
  The compiler can help, but it can't fix the problem any more that it can
  guarantee that a pointer to a local variable doesn't escape once you've
  passed it to another function. In _some_ circumstances, it can catch
  escaping pointers and references, but in the general case, it can't.
 
 See also: http://en.wikipedia.org/wiki/Linear_types
 Stronger and more powerful type systems are possible (D has means to break
 any type system, but the programmer does this knowing what she or he is
 doing. And there are ways similar to @safe to statically disallow the
 means you may use to break this part of the type system).
 
 So, putting classes on the stack kind of negates the whole point of having
 both structs and classes in the first place.
 
 This is false, the definition of D class instance doesn't specify where the
 instance memory is allocated.
 
 In the general case when using SafeD, there D _is_ safe. scoped classes
 are definitely not in SafeD.
 
 SafeD is not safe. It allows integer overflows, memory overflows, etc.
 SafeD just disallows a certain (important) kind of memory bugs. This is
 why some people have asked to call it memory safe.

The whole point of safe when talking about safe in D is memory saftey. And 
scoped classes are an issue of memory safety. They are _not_ safe with regards 
to memory. If the compiler can determine that a particular class object can be 
put on the stack and optimize it that way. Fine, but it's pretty rare that it 
can do that - essentially only in cases where you don't pass it to _anything_ 
except for pure functions (including calls to member functions). And if the 
compiler can do that, then it there's no need for the programmer to use scope 
explicitly.

And no, a compiler _can't_ do pure optimizations on its own, 
generally-speaking, 
because that would require looking not only at the body of the function that's 
being called but at the function bodies of any functions that it calls. D is 
not 
designed in a way that the compiler even necessarily has _access_ to a 
function's body when compiling, and you can't generally look at a function's 
body when doing optimizations when calling that function. So, _some_ pure 
optimizations could be done, but most couldn't. This is not the case with 
scoped 
classes, because purity already gives you the information that you need.

 If you take a look at coding standards that specify how to write high
 integrity software (MISRA-C, SPARK, Joint Strike Fighter Air Vehicle C++
 Coding Standards, etc), you will see that they forbid ALL heap
 allocations, because stack allocations are more deterministic and more
 predictable, so they are safer. If you disallow recursion the max required
 size of the stack is even computable statically, avoiding stack overflows.
 
 -
 
 Nick Voronin:
 Safety is important but you don't achieve safety by means of making unsafe
 thing unconvenient and inefficient.
 
 I know that sounds a little weird, but in practice this is how some parts
 of D are designed :-) Yet, Walter has said many things that he