November 29, 2012
11/29/2012 7:24 AM, Walter Bright пишет:
> On 11/29/2012 4:47 AM, monarch_dodra wrote:
>> On Sunday, 25 November 2012 at 16:47:08 UTC, Dmitry Olshansky wrote:
>>> Thoughts?
>>
>> I don't know about "killing" T(), but I think there *needs* to be an
>> (easy) mechanism to declare ***and*** run-time initialize an object, in
>> a single and comprehensive line.
>>
>> I had proposed something 2 months ago here:
>> http://forum.dlang.org/thread/bvuquzwfykiytdwsqkky@forum.dlang.org
>>
>> The proposal wasn't perfect, but still. We need to figure something
>> out...
>
> The original idea is that there should be *no such thing* as default
> construction of a struct as being anything other than T.init. The
> default construction of a struct should be a compile time creature, not
> a runtime one.
Okay let it be. I'm not against having a defined blank default constructed object.

Just don't make T() mean it, please!

There are a 0-argument constructor or rather a run-time construction that need no arguments. Examples are auto-seeded PRNG, empty containers, digest that typically use default initial vector etc.

Plenty of things. If classes have it why shouldn't structs have one as well? Is there any reason to introduce this discrepancy?

The sudden change of user-defined run-time construction to a biltblit a T.init mask once number of arguments is 0 is a nasty surprise and is a high irregularity in the language.

The unwary may hit a brick wall quite suddenly. Even better example are constructors with all default args:

//simplified
struct A{
	int[] values;
	this(int size=10) //default size...
	{
		values = new int[size];
	}
//...
}

A a = A(20); //okay
A b = A(); //try to pick defaults...
assert(b.values is null); // passes - WTF?

> Any methods or workarounds to try and make T() produce something
> different from T.init is bad D practice.  The compiler tries to
> statically head them off, but probably should do a better job of that.

Why do we have to use T() syntax for this? It blocks 0-argument constructor & ones with all defaults.

Default construction is done either way unless avoided with =void and there is always a T.init. I've spent quite some breath trying to show how T() is unhelpful in any case one needs a default constructed object.

-- 
Dmitry Olshansky
November 29, 2012
> The original idea is that there should be *no such thing* as default construction of a struct as being anything other than T.init. The default construction of a struct should be a compile time creature, not a runtime one.
>
> Any methods or workarounds to try and make T() produce something different from T.init is bad D practice. The compiler tries to statically head them off, but probably should do a better job of that.

The only reason to associate no parameter constructors with default values is because of how C++ works. There is no reason why

Foo foo;                          (1)

should be equivalent to

auto foo = Foo();                 (2)

in D. We could allow constructors with no parameters and make (1) equivalent to

auto foo = Foo.init;              (3)

The current workaround when one wants (2) to construct the object at runtime is to define a static opCall, but that's messy and inconsistent. It's just one more quirk one needs to learn to effectively use the language.
November 29, 2012
On 29/11/2012 16:27, Dmitry Olshansky wrote:
> 11/29/2012 7:24 AM, Walter Bright пишет:
>> The original idea is that there should be *no such thing* as default
>> construction of a struct as being anything other than T.init. The
>> default construction of a struct should be a compile time creature, not
>> a runtime one.
> Okay let it be. I'm not against having a defined blank default
> constructed object.
>
> Just don't make T() mean it, please!
>
> There are a 0-argument constructor or rather a run-time construction
> that need no arguments. Examples are auto-seeded PRNG, empty containers,
> digest that typically use default initial vector etc.
>
> Plenty of things. If classes have it why shouldn't structs have one as
> well? Is there any reason to introduce this discrepancy?
>
> The sudden change of user-defined run-time construction to a biltblit a
> T.init mask once number of arguments is 0 is a nasty surprise and is a
> high irregularity in the language.
>
> The unwary may hit a brick wall quite suddenly. Even better example are
> constructors with all default args:
>
> //simplified
> struct A{
>      int[] values;
>      this(int size=10) //default size...
>      {
>          values = new int[size];
>      }
> //...
> }
>
> A a = A(20); //okay
> A b = A(); //try to pick defaults...
> assert(b.values is null); // passes - WTF?
>
>> Any methods or workarounds to try and make T() produce something
>> different from T.init is bad D practice.  The compiler tries to
>> statically head them off, but probably should do a better job of that.
>
> Why do we have to use T() syntax for this? It blocks 0-argument
> constructor & ones with all defaults.
>
> Default construction is done either way unless avoided with =void and
> there is always a T.init. I've spent quite some breath trying to show
> how T() is unhelpful in any case one needs a default constructed object.

Totally agree with all this. I can't understand why T() should 'default construct' T - it's not default anything if you explicitly type T(). static opCall is an ugly workaround especially in generic wrapper code. Not allowing 0-argument constructors is unintuitive. I have several times tried reading explanations of why it's like this to no avail. If you are allowed to call other runtime constructors, why not zero-arg ones?

struct A{...}
A a; // fine, default construct a
A a = A(); // why does this mean the same thing???

I wish we could deprecate the second syntax as we really need to repurpose it.
November 29, 2012
11/29/2012 9:12 PM, jerro пишет:
>> The original idea is that there should be *no such thing* as default
>> construction of a struct as being anything other than T.init. The
>> default construction of a struct should be a compile time creature,
>> not a runtime one.
>>
>> Any methods or workarounds to try and make T() produce something
>> different from T.init is bad D practice. The compiler tries to
>> statically head them off, but probably should do a better job of that.
>
> The only reason to associate no parameter constructors with default
> values is because of how C++ works. There is no reason why
>
> Foo foo;                          (1)
>
> should be equivalent to
>
> auto foo = Foo();                 (2)
>
> in D. We could allow constructors with no parameters and make (1)
> equivalent to
>
> auto foo = Foo.init;              (3)
>
> The current workaround when one wants (2) to construct the object at
> runtime is to define a static opCall, but that's messy and inconsistent.
> It's just one more quirk one needs to learn to effectively use the
> language.

Yup. It looks like a poorly copied syntactic carry-over from C++ that doesn't quite make sense in the presence of T.init.

-- 
Dmitry Olshansky
November 29, 2012
On Thursday, 29 November 2012 at 12:10:06 UTC, Maxim Fomin wrote:
> On Thursday, 29 November 2012 at 10:41:46 UTC, Mehrdad wrote:
>> I'm just not understanding the whole "the default construction of a struct should be a compile time creature, not a runtime one".
>>
>>
>>
>> Don't you have to initialize the struct with zero's either way?
>>
>> So either way, you're going to have to initialize it... so no perf increase in any way. Why prevent the user from default-initializing it the way he wants to?
>
> Every type has a CT-known default initializer, even classes have (null). If structures had a runtime one, this would break code (especially templates and CTFE) which relies on knowing something about constant default instance of a type at CT.
>
> extern bool foo();
>
> struct S
> {
>   int i;
>   this() {
>     i = foo() ? 1 : -1;
>   }
> }
> ---------
> S s;
> dosmth(s);
> ---------
> //somewhere in Phobos
>
> void dosmth(T) (T obj)
> {
>   T val; // is i 0, -1 or 1 ?
> }

Error, S has no default initializer and must be explicitely initialized.

What is complicated about that ?
November 29, 2012
On Thursday, 29 November 2012 at 17:12:29 UTC, jerro wrote:
>> The original idea is that there should be *no such thing* as default construction of a struct as being anything other than T.init. The default construction of a struct should be a compile time creature, not a runtime one.
>>
>> Any methods or workarounds to try and make T() produce something different from T.init is bad D practice. The compiler tries to statically head them off, but probably should do a better job of that.
>
> The only reason to associate no parameter constructors with default values is because of how C++ works. There is no reason why
>
> Foo foo;                          (1)
>
> should be equivalent to
>
> auto foo = Foo();                 (2)
>
> in D. We could allow constructors with no parameters and make (1) equivalent to
>
> auto foo = Foo.init;              (3)
>
> The current workaround when one wants (2) to construct the object at runtime is to define a static opCall, but that's messy and inconsistent. It's just one more quirk one needs to learn to effectively use the language.

This do not solve problem with heap allocated struct being moved, but is definitively the right direction.
November 29, 2012
On Thursday, November 29, 2012 20:27:32 Dmitry Olshansky wrote:
> 11/29/2012 7:24 AM, Walter Bright пишет:
> > On 11/29/2012 4:47 AM, monarch_dodra wrote:
> >> On Sunday, 25 November 2012 at 16:47:08 UTC, Dmitry Olshansky wrote:
> >>> Thoughts?
> >> 
> >> I don't know about "killing" T(), but I think there *needs* to be an
> >> (easy) mechanism to declare ***and*** run-time initialize an object, in
> >> a single and comprehensive line.
> >> 
> >> I had proposed something 2 months ago here: http://forum.dlang.org/thread/bvuquzwfykiytdwsqkky@forum.dlang.org
> >> 
> >> The proposal wasn't perfect, but still. We need to figure something out...
> > 
> > The original idea is that there should be *no such thing* as default construction of a struct as being anything other than T.init. The default construction of a struct should be a compile time creature, not a runtime one.
> 
> Okay let it be. I'm not against having a defined blank default constructed object.
> 
> Just don't make T() mean it, please!

I'm all for T() meaning T.init if T doesn't have a static opCall, but T() shouldn't be guaranteed to be T.init. I'd very much like to see code like

auto t = T();

to continue to work regardless of whether T has a static opCall or not. But it should be able to have a static opCall, and T() should work if it doesn't have one. Assuming that T() means T.init makes no sense.

- Jonathan M Davis
November 30, 2012
On Thursday, 29 November 2012 at 23:31:54 UTC, Jonathan M Davis wrote:
> I'm all for T() meaning T.init if T doesn't have a static opCall, but T()
> shouldn't be guaranteed to be T.init. I'd very much like to see code like
>
> auto t = T();
>
> to continue to work regardless of whether T has a static opCall or not. But it
> should be able to have a static opCall, and T() should work if it doesn't have
> one. Assuming that T() means T.init makes no sense.
>

opCall is really a poor workaround because it doesn't allow new, it is inconsistent with other constructors and is unexpected by the user.

How much opCall has spread tells more about how parameterless constructor is needed than something else.
November 30, 2012
On 11/29/2012 3:59 PM, Mehrdad wrote:
> On Thursday, 29 November 2012 at 03:24:40 UTC, Walter Bright wrote:
>> The original idea is that there should be *no such thing* as default
>> construction of a struct as being anything other than T.init. The
>> default construction of a struct should be a compile time creature,
>> not a runtime one.
>
>
> Why?

So copying them is always an unsurprising bit copy.
November 30, 2012
On 11/30/2012 2:21 PM, Walter Bright wrote:
> On 11/29/2012 3:59 PM, Mehrdad wrote:
>> On Thursday, 29 November 2012 at 03:24:40 UTC, Walter Bright wrote:
>>> The original idea is that there should be *no such thing* as default
>>> construction of a struct as being anything other than T.init. The
>>> default construction of a struct should be a compile time creature,
>>> not a runtime one.
>>
>>
>> Why?
>
> So copying them is always an unsurprising bit copy.

Eh, scratch that.

It was so initialization is always an unsurprising bit copy. It means, for example, that the constructor for a struct never sees uninitialized fields.