View mode: basic / threaded / horizontal-split · Log in · Help
November 29, 2012
Re: Time to kill T() as (sometimes) working T.init alias ?
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
Re: Time to kill T() as (sometimes) working T.init alias ?
> 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
Re: Time to kill T() as (sometimes) working T.init alias ?
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
Re: Time to kill T() as (sometimes) working T.init alias ?
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
Re: Time to kill T() as (sometimes) working T.init alias ?
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
Re: Time to kill T() as (sometimes) working T.init alias ?
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
Re: Time to kill T() as (sometimes) working T.init alias ?
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
Re: Time to kill T() as (sometimes) working T.init alias ?
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
Re: Time to kill T() as (sometimes) working T.init alias ?
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
Re: Time to kill T() as (sometimes) working T.init alias ?
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.
1 2 3 4 5 6
Top | Discussion index | About this forum | D home