May 15, 2013
On 5/15/13 5:14 PM, Walter Bright wrote:
> It means I can't read the code and easily determine what that const
> value is, even though it is explicitly initialized with a value.

I now understand the concern. I'd argue that static immutable/const fulfills that role, and that a member const is supposed to be initialized in a constructor (or via the default initializer syntax as for any other member) and stay constant throughout the lifetime of the object. That _is_ a very useful notion.

I'm not assuming you're proposing this, but I'm clarifying just in case: a member that takes per-instance memory YET always has the same value in all objects would be positively useless. _That_ should at best be an error.


Andrei
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

May 15, 2013
On Wednesday, May 15, 2013 22:33:45 Leandro Lucarella wrote:
> I think it make more sense to put the default in the constructor argument instead of in the member variable declaration. In that case is pretty clear, but if the member declaration is far from the constructor, one could easily assume scalingFactor is always 1.0.

Except that structs don't have default constructors, so if you're dealing with the init value, you're going to have to directly initialize the member. There _are_ plenty of cases though where using a default argument would make good sense. It just doesn't help the init value any.

- Jonathan M Davis
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

May 16, 2013
On 15 May 2013 23:19, Andrei Alexandrescu <andrei@erdani.com> wrote:

> On 5/15/13 5:14 PM, Walter Bright wrote:
>
>> It means I can't read the code and easily determine what that const value is, even though it is explicitly initialized with a value.
>>
>
> I now understand the concern. I'd argue that static immutable/const fulfills that role, and that a member const is supposed to be initialized in a constructor (or via the default initializer syntax as for any other member) and stay constant throughout the lifetime of the object. That _is_ a very useful notion.
>
> I'm not assuming you're proposing this, but I'm clarifying just in case: a member that takes per-instance memory YET always has the same value in all objects would be positively useless. _That_ should at best be an error.
>

Great! This is exactly my argument. In that case we are actually in agreement. Thats the case I want to disallow.


May 16, 2013
On 05/15/2013 11:19 PM, Andrei Alexandrescu wrote:
> On 5/15/13 5:14 PM, Walter Bright wrote:
>> It means I can't read the code and easily determine what that const
>> value is, even though it is explicitly initialized with a value.
>
> I now understand the concern. I'd argue that static immutable/const
> fulfills that role, and that a member const is supposed to be
> initialized in a constructor (or via the default initializer syntax as
> for any other member) and stay constant throughout the lifetime of the
> object. That _is_ a very useful notion.
>
> I'm not assuming you're proposing this, but I'm clarifying just in case:
> a member that takes per-instance memory YET always has the same value in
> all objects would be positively useless. _That_ should at best be an error.

Are you proposing that this be allowed:

  struct S
  {
      immutable int c = 123;
      this(int i) { c = i; }
  }

and that the compiler should report an error on the following?

  struct S
  {
      immutable int c = 123;
      // No constructor
  }

Lars
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

May 16, 2013
On Thu, May 16, 2013 at 11:33 AM, Lars Tandle Kyllingstad < lars@kyllingen.net> wrote:

> Are you proposing that this be allowed:
>
>   struct S
>   {
>       immutable int c = 123;
>       this(int i) { c = i; }
>   }
>
> and that the compiler should report an error on the following?
>
>   struct S
>   {
>       immutable int c = 123;
>       // No constructor
>   }
>

As I understand, he is proposing that either the first code snippet be allowed OR the second one should be an error.

Regards
- Puneet


May 16, 2013
  struct S
  {
      immutable int c = 123; // I agree with Walter, what if this is far
away from the constructor
      this(int i) { c = i; }
  }

  struct S
  {
      immutable int c = 123; // This should be static, compiler issues error
      // No constructor
  }

would it be possible to disallow a default initializer for const / immutable member variables and instead allow a single assignment from the constructor?

That way you can supply the default in the constructors arguments, and everyone can see exactly what is going on. In the cases where the variable's value cannot be overridden you HAVE to use static with a default initializer.


On Thu, May 16, 2013 at 8:16 AM, d coder <dlang.coder@gmail.com> wrote:

>
> On Thu, May 16, 2013 at 11:33 AM, Lars Tandle Kyllingstad < lars@kyllingen.net> wrote:
>
>> Are you proposing that this be allowed:
>>
>>   struct S
>>   {
>>       immutable int c = 123;
>>       this(int i) { c = i; }
>>   }
>>
>> and that the compiler should report an error on the following?
>>
>>   struct S
>>   {
>>       immutable int c = 123;
>>       // No constructor
>>   }
>>
>
> As I understand, he is proposing that either the first code snippet be allowed OR the second one should be an error.
>
> Regards
> - Puneet
>
> _______________________________________________
> dmd-beta mailing list
> dmd-beta@puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-beta
>


May 16, 2013
2013/5/16 Don Clugston <dclugston@gmail.com>

> On 15 May 2013 23:19, Andrei Alexandrescu <andrei@erdani.com> wrote:
>>
>> I'm not assuming you're proposing this, but I'm clarifying just in case:
>> a member that takes per-instance memory YET always has the same value in
>> all objects would be positively useless. _That_ should at best be an error.
>>
>
> Great! This is exactly my argument. In that case we are actually in agreement. Thats the case I want to disallow.
>

Why it should be error? Yes, it would be finally redundant, but the redundancy is necessary to keep meta-programming simple.

import std.traits;
struct MyData(T) if (isIntegral!T) {
    T value = 10;   // provides default value
    alias value this;
    this(T v) { value = v; }
}

With 2.062 and earlier, this simple MyData struct did not work when T is non-mutable integer type. To support it, it had been required that checking T is non-mutable and then remove constructor.

import std.traits;
struct MyData(T) if (isIntegral!T) {
    T value = 10;   // provides default value
    alias value this;
    static if (!is(T == const) && !is(T == immutable))
    {   // necessary for 2.062 and earlier
        this(T v) { value = v; }
    }
}

This is definitely unnecessary complexity. Why you need this?

D should have ability for writing efficient code, but D should not enforce writing efficient code to users.

Kenji Hara


May 16, 2013
On 16/05/2013 08:48, Rory McGuire wrote:
>
> struct S
>    {
>        immutable int c = 123; // I agree with Walter, what if this is
> far away from the constructor
>        this(int i) { c = i; }
>    }
>
>    struct S
>    {
>        immutable int c = 123; // This should be static, compiler issues
> error
>        // No constructor
>    }
>
> would it be possible to disallow a default initializer for const /
> immutable member variables and instead allow a single assignment from
> the constructor?

You can't disallow default initialisers in general, e.g. in the first case above, because then the programmer no longer has the power to decide what S.init should look like.  I don't think that is acceptable.

Don may be right that it is necessary to require 'static' in the second case, though, to avoid silent breakage.

Lars

_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

May 16, 2013
Rory McGuire, el 16 de May a las 08:48 me escribiste:
>   struct S
>   {
>       immutable int c = 123; // I agree with Walter, what if this is far
> away from the constructor
>       this(int i) { c = i; }
>   }
> 
>   struct S
>   {
>       immutable int c = 123; // This should be static, compiler issues error
>       // No constructor
>   }

There are cases where you might want this. Suppose you're implementing a network protocol and you have a header to indicate what kind of packet you have. Example:

struct P1 {
        immutable int type = 1;
        int param1;
}

struct P2 {
        immutable int type = 2;
        long param1;
}

The type field *needs* to be part of the struct layout so is sent through the wire, but it won't change for a particular struct, ever. Remember that memory layout matters in a struct.

I know there are ways around this, I'm just saying there are even use cases for that case too.


-- 
Leandro Lucarella (AKA luca)                     http://llucax.com.ar/
----------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------
Yo soy Peperino, mártir latino, venid al asado pero traed el vino.
	-- Peperino Pómoro
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta
May 16, 2013
Wall of text incoming.

First. I'd like to remind to several important properties of D structs:

* They have both compile-time initialization and run-time one. First is T.init, second is T(...). Needing both is a perfectly valid need from the programmer, especially with generic code in question.

* structs always have constructors. So this snippet is wrong:
>   struct S
>   {
>       immutable int c = 123; // This should be static, compiler issues error
>       // No constructor
>   }
In fact, S has constructor. All structs have constructor with parameter count that matches member field count. And judging only by S definition you can't ever possibly say if "c" will be the same in all S instances or not.

Second. Having parts of a struct essentially immutable is a common technique used in, for example, packet template generation in C. C does not have immutability and a convention is used, but principle is the same - struct defines packet frame layout, different instances of struct define different pre-computed packet templates, mutable fields define data that may differ in actual sent packets within one template. I am sure there are other valid usages in areas I am not so familiar with.

Third. Consistency is very important. Design based on use cases is good only within a reasonable limits. If user can't guess behavior of a type system based on previous experience, it causes frustration. There can be a simple and robust approach:

struct S
{
    int x1;                     // mutable data of int size, separate instances
    const int x2;           // const data of int size, separate instances
    static const int x3; // const data of int size, single instance
for all S instances. But still exists in memory.
    enum int x4 = 42;  // named integer literal. No size, no actual
place in memory.
}

Such approach is good because of two reasons. It is orthogonal in a sense that every type qualifier / storage class adds certain well-defined property to a type which does not depends on any special case. Second, it is consistent because it stays the same both for struct members and local variables. This is much more important than prohibiting something based on use case approach.

Third. While new behavior is correct and Don's code relied on long-standing bug DMD still absolutely must provide easy tool to make required changes. It does not matter if code was correct or not - it is a difficult breaking change and all words about D stability being a goal are essentially a nonsense until such attitude is not a default. Compiler flag added by Kenji is a good solution, but it should not be _special_ solution, it needs to become a default way to go.

Best regards,
Dicebot
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta