May 23, 2013
On Thu, 23 May 2013 11:14:47 -0400, Steven Schveighoffer <schveiguy@yahoo.com> wrote:

> On Thu, 23 May 2013 11:07:16 -0400, Dicebot <m.strashun@gmail.com> wrote:
>
>> On Thursday, 23 May 2013 at 14:58:01 UTC, Steven Schveighoffer wrote:
>>> Seems like const qualifier for members is simply ignored inside the ctor, it should only be ignored until it is set, or until it is used.
>>
>> I am quite sure I have seen it (mutability of immutable in constructor) guaranteed either by spec or TDPL. Don't have TDPL with me right now, need to check later.
>
> I did check, though not thoroughly.  I think it only talks about actual immutable constructors (that is, initializing a fully immutable-qualified instance).  It doesn't really talk about immutable members.
>
> And for immutable constructors, the rule seems to be that you can assign fields as many times as you want, but you cannot read them, or call any methods.
>
> I think whatever rules are used, they should be consistent for immutable/const members as well.

Actually, this is a bad idea.  TDPL may need to be invalidated here.

If this was followed, then normal mutable ctors would become as limited as immutable ctors because they would have to follow the same rules (no calling other methods).

I still think it should be consistent between both things (immutable ctors and initializing immutable data).

I'll post a thread on standard NG.

-Steve
May 23, 2013
On Thu, May 23, 2013 at 5:24 PM, Dicebot <m.strashun@gmail.com> wrote:

> On Thursday, 23 May 2013 at 15:15:18 UTC, Rory McGuire wrote:
>
>> b) it requires to know your argument at compile-time. What if you packet
>>> construction is based on some text configuration file?
>>>
>>>
>> :) I'm sure we could think of something wrong with any part of the
>> language
>> if we really wanted to.
>>
>
> Well, you see, I am not imagining it. Had to write a barebone traffic generation tool in C several months ago for project. It did almost exactly that, only with no help support from type system, of course.
>

Hence the smile. It is a valid case as are most valid cases :) but We're discussing which of the two happens more often. I think this is rare enough to type an extra "!". In Go they would probably make it illegal, simply because its confusing for most cases.


May 23, 2013
On 5/23/13 6:16 AM, Peter Alexander wrote:
> On Thursday, 23 May 2013 at 09:05:02 UTC, Don wrote:
>> This means that the const variable x has been initialized TWICE!
>
> That's no different from non-const members.
>
> struct Foo { int x = 1; }
> Foo f = Foo(2); // f.x is 2
>
> The initialiser is a default value if you don't provide one in the
> constructor. If you don't mark a variable as static then it is not
> static and needs to be initialised like any other member variable.
>
>
>> This new behaviour is counter-intuitive and introduces a horrible
>> inconsistency.
>
> It is exactly what happens in C++ and causes no confusion there.
>
>
>> This is totally different to what happens with module constructors
>> (you get a compile error if you try to set a const global if it
>> already has an initializer).
>
> In structs/classes, it is not an initialiser, it is a default value in
> case you don't provide a different value.
>
>
>> As far as I can tell, this new feature exists only to create bugs. No
>> use cases for it have been given. I cannot imagine a case where using
>> this feature would not be a bug.
>
> The use case is simple: to allow non-static const member variables.

The point is, this is a silent change of behavior. (I agree the new behavior is sensible.)

Andrei
May 23, 2013
On Thursday, 23 May 2013 at 14:42:27 UTC, Dicebot wrote:
> something I may have actually used in real code writing a low-level networking library:
>
> struct Packet
> {
> 	immutable etherType = 0x0800; // IPv4 by default;
> 	
> 	// ...
> 	
> 	this(bool IPv6)
> 	{
> 		if (!IPv6)
> 			return; // fine with default, same as Packet.init
> 		else
> 		{
> 			etherType = 0x86DD;
> 			// ...
> 		}
> 	}
> }
>
> void main()
> {
> 	auto buffer = cast(ubyte[])(Packet(true));
> }

That's better, but it's still not a convincing example.

I don't see why you cannot remove the intializer, and write:

this(bool IPv6)
{
    if (!IPv6)
      etherType = 0x0800;
    else
      etherType = 0x86DD;
  ...
}

That only leaves the case where you are bypassing the constructor.
If you have a constructor, but have just used Packet.init, the object is not constructed properly. I cannot see the value in having etherType initialized and everything else not.

May 23, 2013
On 05/23/13 16:02, Steven Schveighoffer wrote:
> On Thu, 23 May 2013 09:50:28 -0400, Artur Skawina <art.08.09@gmail.com> wrote:
> 
>> On 05/23/13 15:12, Don wrote:
>>> On Thursday, 23 May 2013 at 11:08:16 UTC, Artur Skawina wrote:
> 
>>>> struct Packet(uint TYPE) {
>>>>    immutable uint type = TYPE;
>>>>    // ...
>>>> }
>>>
>>> But that allows you to write:
>>>
>>> auto w  = Packet!(7)(6);
>>>
>>> which sets type to 6 !
>>
>> No, it doesn't - this is why the "const and initialized, but still mutable" class is a bad idea. Modifying already initialized immutable data needs to be forbidden.
> 
> There is a misconception here.  The data is not fully initialized when the ctor is called, it's just that the memory where the instance lives happens to have a bit pattern in it with the value 7 when the ctor gets it.
> 
> It's no different than a non-default initialized immutable being "initialized" to 0 first before you set it.  It's just you get to define the bit pattern instead of using 0.
> 
> In order to disable the behavior above, you have to disable the default ctor, define a non-default ctor, or generate using a static method/function.

If it wasn't clear - it is about the _language_, not what some compiler currently happens to do. Being able to mutate /initialized/ immutables is a bad idea. IOW you should not be able to modify 'Packet.type' above.

Keep in mind that modifying Packet.type is illegal /right now/. Even from
a ctor or static-ctor. This does not need to change when such fields are
no longer always implicitly static. While allowing re-initialization
of immutables from a ctor is possible, it does not really give you much,
while weakening const. (eg by making CT evaluation of such fields impossible).

artur
May 23, 2013
On Thursday, 23 May 2013 at 13:52:49 UTC, Steven Schveighoffer wrote:
> On Thu, 23 May 2013 05:05:01 -0400, Don <turnyourkidsintocash@nospam.com> wrote:
>
>> On Tuesday, 21 May 2013 at 20:36:20 UTC, Walter Bright wrote:
>>>
>>> Join the dmd beta mailing list to keep up with the betas. This one is pretty much good to go, unless something disastrous crops up.
>>>
>>> http://ftp.digitalmars.com/dmd2beta.zip
>>>
>>> Remaining regressions:
>>>
>>> http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&bug_severity=regression&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED
>>
>> NO NO NO NO. I am violently opposed to this release.
>>
>> This beta contains the worst language misfeature of all time. It's silently snuck in under the guise of a bugfix.
>>
>>
>> struct S
>> {
>>     const int x = 7;
>>     int y;
>> }
>>
>> In previous releases, S.x was always 7.
>> But now, if you write
>>
>> S s = S(5);
>>
>> then x gets changed to 5.
>> This means that the const variable x has been initialized TWICE!
>
>> This new behaviour is counter-intuitive and introduces a horrible inconsistency.
>
> I disagree.
>
> struct S
> {
>      const int x;
> }
>
> S s1; // x is 0


Of course! It's an uninitialized variable! Try making x a float, and you'll get NaN.

> S s2 = S(5); // x is 5

---
> I can see uses.  If you don't want x.init to be the default for x, then you need to set it to something else.
>
> For example:
>
> struct Widget
> {
>    immutable string name = "(unset)"; // instead of ""
> }

That is just an awful workaround for the lack of default constructors.
May 23, 2013
On Thu, 23 May 2013 11:36:00 -0400, Artur Skawina <art.08.09@gmail.com> wrote:

> If it wasn't clear - it is about the _language_, not what some compiler
> currently happens to do. Being able to mutate /initialized/ immutables
> is a bad idea. IOW you should not be able to modify 'Packet.type' above.

The immutable isn't initialized.  The memory it happens to be using before initialization happens to have the '7' bit pattern in it.

Once it is initialized, I agree it should be immutable from that point on.

> Keep in mind that modifying Packet.type is illegal /right now/. Even from
> a ctor or static-ctor. This does not need to change when such fields are
> no longer always implicitly static. While allowing re-initialization
> of immutables from a ctor is possible, it does not really give you much,
> while weakening const. (eg by making CT evaluation of such fields impossible).

That's an issue of where Packet.type lives.  It doesn't live inside an instance right now, in the new version it does.

If Packet.type is not given an initializer, it's inside the instance and it (correctly IMO) can be modified inside a ctor until it is used.

These rules are perfectly consistent.

I don't see how they make CT evaluation impossible.

-Steve
May 23, 2013
On 23 May 2013 19:05, Don <turnyourkidsintocash@nospam.com> wrote:

> On Tuesday, 21 May 2013 at 20:36:20 UTC, Walter Bright wrote:
>
>>
>> Join the dmd beta mailing list to keep up with the betas. This one is pretty much good to go, unless something disastrous crops up.
>>
>> http://ftp.digitalmars.com/**dmd2beta.zip<http://ftp.digitalmars.com/dmd2beta.zip>
>>
>> Remaining regressions:
>>
>> http://d.puremagic.com/issues/**buglist.cgi?query_format=**
>> advanced&bug_severity=**regression&bug_status=NEW&bug_**
>> status=ASSIGNED&bug_status=**REOPENED<http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&bug_severity=regression&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED>
>>
>
> NO NO NO NO. I am violently opposed to this release.
>
> This beta contains the worst language misfeature of all time. It's silently snuck in under the guise of a bugfix.
>

Side note, it's so funny how I can clearly hear everybody's voice and
inflections when reading the NG now!
This post in particular :)

struct S
> {
>     const int x = 7;
>     int y;
> }
>
> In previous releases, S.x was always 7.
> But now, if you write
>
> S s = S(5);
>
> then x gets changed to 5.
> This means that the const variable x has been initialized TWICE!
>
> This new behaviour is counter-intuitive and introduces a horrible inconsistency.
>
> This is totally different to what happens with module constructors (you get a compile error if you try to set a const global if it already has an initializer). Likewise, everywhere else in the language, when you see a const variable with an initializer, the initializer gives its value.
>
>
> I think the only possible solution is to make it an error to provide a const or immutable member with an initializer.
>
> If you are providing an initializer, you surely meant to make it 'static const', and that is certainly true of all existing usages of it.
>
> As far as I can tell, this new feature exists only to create bugs. No use cases for it have been given. I cannot imagine a case where using this feature would not be a bug.
>
>
> Please do not release this beta.
>


May 23, 2013
On Thu, 23 May 2013 12:09:26 -0400, Don <turnyourkidsintocash@nospam.com> wrote:

> On Thursday, 23 May 2013 at 13:52:49 UTC, Steven Schveighoffer wrote:
>> On Thu, 23 May 2013 05:05:01 -0400, Don <turnyourkidsintocash@nospam.com> wrote:
>>
>>> On Tuesday, 21 May 2013 at 20:36:20 UTC, Walter Bright wrote:
>>>>
>>>> Join the dmd beta mailing list to keep up with the betas. This one is pretty much good to go, unless something disastrous crops up.
>>>>
>>>> http://ftp.digitalmars.com/dmd2beta.zip
>>>>
>>>> Remaining regressions:
>>>>
>>>> http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&bug_severity=regression&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED
>>>
>>> NO NO NO NO. I am violently opposed to this release.
>>>
>>> This beta contains the worst language misfeature of all time. It's silently snuck in under the guise of a bugfix.
>>>
>>>
>>> struct S
>>> {
>>>     const int x = 7;
>>>     int y;
>>> }
>>>
>>> In previous releases, S.x was always 7.
>>> But now, if you write
>>>
>>> S s = S(5);
>>>
>>> then x gets changed to 5.
>>> This means that the const variable x has been initialized TWICE!
>>
>>> This new behaviour is counter-intuitive and introduces a horrible inconsistency.
>>
>> I disagree.
>>
>> struct S
>> {
>>      const int x;
>> }
>>
>> S s1; // x is 0
>
>
> Of course! It's an uninitialized variable! Try making x a float, and you'll get NaN.

No, it's initialized to NaN.  If it was truly uninitialized, then it would be garbage, like C.

In other words, *something* writes NaN into that memory location (or 0, or whatever).  The initializer simply dictates what to write.

>> S s2 = S(5); // x is 5
>
> ---
>> I can see uses.  If you don't want x.init to be the default for x, then you need to set it to something else.
>>
>> For example:
>>
>> struct Widget
>> {
>>    immutable string name = "(unset)"; // instead of ""
>> }
>
> That is just an awful workaround for the lack of default constructors.

Why?  The compiler blits a bit-pattern onto the struct before initialization.  Why should we not be given the ability to control that bit pattern?  It's just data!

I find the argument against this quite puzzling, we should have as much power as possible over how the compiler treats our custom types.  I think your arguments simply stem from the fact that you did not specify static for your static variables, and the compiler loosely accepted that until now.

-Steve
May 23, 2013
On Tuesday, 21 May 2013 at 20:36:20 UTC, Walter Bright wrote:
>
> Join the dmd beta mailing list to keep up with the betas. This one is pretty much good to go, unless something disastrous crops up.
>
> http://ftp.digitalmars.com/dmd2beta.zip
>
> Remaining regressions:
>
> http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&bug_severity=regression&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED

Add that one : http://d.puremagic.com/issues/show_bug.cgi?id=10151

Once again my code is broken. I can understand both behavior, but the change don't really make sense. This time the ROI is doubtful.