May 16, 2013
Am 16.05.2013 10:09, schrieb TommiT:
> On Thursday, 16 May 2013 at 07:59:20 UTC, dennis luehring wrote:
>> doesn't that break the constness for other threads usage?
>>
>> (not in your example - but in any other using threads, const
>> globals and your proposed "initialization")
>
> I'm sorry, somehow I just don't understand the question.
>

in short: your proposal breaks const thread access safetiness

and there are 3 other solutions down here

1. static this () { }
2. 2 functions returning into consts
3. a class with init in ctor + lookup funcs in const ref

so there is not need for an "initialization" feature
May 16, 2013
Am 16.05.2013 10:14, schrieb TommiT:
> On Thursday, 16 May 2013 at 08:02:05 UTC, Jacob Carlborg wrote:
>> Use a module constructor:
>>
>> static this () { }
>>
>> http://dlang.org/module.html#staticorder
>
> On Thursday, 16 May 2013 at 08:01:44 UTC, Timothee Cour wrote:
>> this works:
>>
>>
>> import std.stdio;
>> import std.conv;
>> const string[100] int__str;
>> const int[string] str__int;
>>
>> static this(){
>>     for (int i = 0; i < 100; ++i)
>>     {
>>         auto str = to!string(i);
>>         int__str[i] = str; // ERROR: Can't modify const
>>         str__int[str] = i; // ERROR: Can't modify const
>>     }
>> }
>
> But I'm talking about function local data. The initialization of
> that data might depend on the arguments passed to the function.
>

so youre example code isn't showing what you try to reach - makes it hard to understand/help - its even unclear if your string[100], int[string] is just an example or a real problem, or if your < 100 is variant or const - come up with an clear example

the normal way of doing stuff like this in C++,Java and D would be
and helper class with const members and const methods for access









May 16, 2013
On Thursday, May 16, 2013 10:20:16 TommiT wrote:
> On Thursday, 16 May 2013 at 08:01:33 UTC, deadalnix wrote:
> > This is easy to work around that using a mutable data, construct it and then copy it to a const one.
> > 
> > You my argue that this is slower, and I answer you : maybe. Can you show what does GDC or LDC output doing so ?
> 
> I could also argue that it's just not very elegant solution. You're left with this extra, useless dummy variable (the initial, mutable one) that you're not supposed to use.
> 
> Also, I'd like to initialize immutable variables plus there's the possible performance issue (don't have time to do a test now).

Well, that's the standard way to do it. If you can't initialize a const or immutable variable in one go, you create a mutable one and then cast it (or use assumeUnique) on it and assign it to the const/immutable variable that you wanted to initialize. For module-level and static variables, you'd generally do it in a static constructor, though that isn't an option for local variables. In their case though, if you don't want two variables floating around, you can always use a nested function (or some other function) to generate the mutable variable and then return it as const or immutable.

Normally, there's no performance hit to doing any of this, but it is true that that's a potential issue in your example, because it's a static variable. I question that that merits adding a new feature to the language though. The trick of creating it as mutable and then casting it to immutable works quite well overall and really hasn't been causing problems.

- Jonathan M Davis
May 16, 2013
Against.
May 16, 2013
what's more fundamentally missing is ability to use ref on variables. DIP39 should be able to be adapted to that case.

 void main(){
    int[1000] x1_;
    int[1000] x2_;
    // do some initialization on x1_,x2_
    const(typeof(x)) x1=x1_;  //wishful thinking
    const(typeof(x)) x2=x2_;  //ditto
    assert(&x1 is &x1_); // no copy
}


May 16, 2013
2013/5/16 TommiT <tommitissari@hotmail.com>

> I'd like to make it easier to initialize function local immutable/const data. Here's the type of problem I'd like to alleviate:
>
> const string[100] int__str;
> const int[string] str__int;
>
> for (int i = 0; i < 100; ++i)
> {
>     auto str = to!string(i);
>     int__str[i] = str; // ERROR: Can't modify const
>     str__int[str] = i; // ERROR: Can't modify const
> }
>
> In short, I want to initialize two different const variables at once (in the same loop or other block). If I needed to initialize only one const variable, I could use a lambda:
>
> const string[100] int__str = {
>     string[100] tmp;
>     // ... init tmp ...
>     return tmp;
> }();
>
> ...But I can't see any easy solution for initializing two or more const variables at the same time.
>
> Here's my proposal: "initialization scope". You'd use it like this:
>
> initialization {
>     const string[100] int__str;
>     const int[string] str__int;
>
>     for (int i = 0; i < 100; ++i)
>     {
>         auto str = to!string(i);
>         int__str[i] = str; // OK
>         str__int[str] = i; // OK
>     }
> }
>
> string s = int__str[42]; // OK
> int__str[42] = "43" // ERROR: Can't modify const
>
> As you can see, 'initialization scope' would be a scope that is not a lexical scope (like static if), it merely makes all const and immutable variables created in that scope modifiable inside that scope but not after it.
>

Pure delegate and implicit conversion for unique expression should work.

import std.conv;
void main()
{
    immutable string[100] int__str = () pure {
        string[100] tmp;
        debug printf("&tmp[0] = %p\n", &tmp[0]);        // [1]
        for (int i = 0; i < 100; ++i)
        {
            auto str = to!string(i);
            // BUG: pure function '__lambda1' cannot call impure function
'to'
            tmp[i] = str;
        }
        return tmp; // BUG: NRVO doesn't work
    }();
    debug printf("&int__str[0] = %p\n", &int__str[0]);  // [2]
}

Compiler bug: Currently [1] and [2] does not print same address. Phobos bug: Currently std.conv.to is not pure.

Kenji Hara


May 16, 2013
On Thursday, 16 May 2013 at 08:31:27 UTC, Jonathan M Davis wrote:
> Normally, there's no performance hit to doing any of this, but it is true that
> that's a potential issue in your example, because it's a static variable. [..]

I assume you mean the variable is statically allocated. Which, I assume, means that there's an actual memory copy involved when such variable is cast to immutable.

Here's some more of the logic behind my suggestion:

Any hoops, that the programmer has to go through in order to make his function-local variable a const/immutable, discourages him from making the variable const/immutable. To me, it seems that the path of least resistance for the programmer is simply not make it const/immutable. By discouraging const-correctness we encourage writing bugs.
May 16, 2013
simplified case:

doesn't work with NRVO:
 void main(){
    immutable int[10] x = () pure {
        int[10] x_;
        debug printf("&x_[0] = %p\n", &x_[0]);
        return x_;
    }();
    debug printf("&x[0] = %p\n", &x[0]);  // prints different address
}


doesn't work with RVO:
 struct A{
    int[10] x_;
    this(int _ignore)pure{
        foo();
    }
    void foo()const pure{
        debug printf("&x_[0] = %p\n", &x_[0]);
    }
}
void main(){
    immutable A a = () pure {
        return A(0);
    }();
    a.foo();
}


is RVO even happening?

On Thu, May 16, 2013 at 1:55 AM, Kenji Hara <k.hara.pg@gmail.com> wrote:

> 2013/5/16 TommiT <tommitissari@hotmail.com>
>
>> I'd like to make it easier to initialize function local immutable/const data. Here's the type of problem I'd like to alleviate:
>>
>> const string[100] int__str;
>> const int[string] str__int;
>>
>> for (int i = 0; i < 100; ++i)
>> {
>>     auto str = to!string(i);
>>     int__str[i] = str; // ERROR: Can't modify const
>>     str__int[str] = i; // ERROR: Can't modify const
>> }
>>
>> In short, I want to initialize two different const variables at once (in the same loop or other block). If I needed to initialize only one const variable, I could use a lambda:
>>
>> const string[100] int__str = {
>>     string[100] tmp;
>>     // ... init tmp ...
>>     return tmp;
>> }();
>>
>> ...But I can't see any easy solution for initializing two or more const variables at the same time.
>>
>> Here's my proposal: "initialization scope". You'd use it like this:
>>
>> initialization {
>>     const string[100] int__str;
>>     const int[string] str__int;
>>
>>     for (int i = 0; i < 100; ++i)
>>     {
>>         auto str = to!string(i);
>>         int__str[i] = str; // OK
>>         str__int[str] = i; // OK
>>     }
>> }
>>
>> string s = int__str[42]; // OK
>> int__str[42] = "43" // ERROR: Can't modify const
>>
>> As you can see, 'initialization scope' would be a scope that is not a lexical scope (like static if), it merely makes all const and immutable variables created in that scope modifiable inside that scope but not after it.
>>
>
> Pure delegate and implicit conversion for unique expression should work.
>
> import std.conv;
> void main()
> {
>     immutable string[100] int__str = () pure {
>         string[100] tmp;
>         debug printf("&tmp[0] = %p\n", &tmp[0]);        // [1]
>         for (int i = 0; i < 100; ++i)
>         {
>             auto str = to!string(i);
>             // BUG: pure function '__lambda1' cannot call impure function
> 'to'
>             tmp[i] = str;
>         }
>         return tmp; // BUG: NRVO doesn't work
>     }();
>     debug printf("&int__str[0] = %p\n", &int__str[0]);  // [2]
> }
>
> Compiler bug: Currently [1] and [2] does not print same address. Phobos bug: Currently std.conv.to is not pure.
>
> Kenji Hara
>


May 16, 2013
On Thursday, 16 May 2013 at 08:20:17 UTC, TommiT wrote:
> Also, I'd like to initialize immutable variables plus there's the possible performance issue (don't have time to do a test now).

I don't think you should come up with proposal if you don't want to explore the implications.
May 16, 2013
TommiT:

> If I needed to initialize only one const variable, I could use a lambda:
>
> const string[100] int__str = {
>     string[100] tmp;
>     // ... init tmp ...
>     return tmp;
> }();
>
> ...But I can't see any easy solution for initializing two or more const variables at the same time.

Once we have a tuple unpacking syntax, you return and assign to two const variables at the same time.

Bye,
bearophile