digitalmars.D - New feature proposal: "initialization scope"
- TommiT (39/39) May 16 2013 I'd like to make it easier to initialize function local
- dennis luehring (4/43) May 16 2013 doesn't that break the constness for other threads usage?
- Timothee Cour (14/69) May 16 2013 this works:
- TommiT (2/5) May 16 2013 I'm sorry, somehow I just don't understand the question.
- dennis luehring (7/13) May 16 2013 in short: your proposal breaks const thread access safetiness
- deadalnix (5/24) May 16 2013 This is easy to work around that using a mutable data, construct
- dennis luehring (3/32) May 16 2013 or even better - make them members of an helper class, with lookup
- TommiT (6/10) May 16 2013 I could also argue that it's just not very elegant solution.
- Jonathan M Davis (15/28) May 16 2013 Well, that's the standard way to do it. If you can't initialize a const ...
- TommiT (11/15) May 16 2013 I assume you mean the variable is statically allocated. Which, I
- Jonathan M Davis (11/28) May 16 2013 I mistyped. I meant static array. The variable isn't static. But yes, th...
- deadalnix (3/6) May 16 2013 I don't think you should come up with proposal if you don't want
- Jacob Carlborg (6/18) May 16 2013 Use a module constructor:
- TommiT (4/20) May 16 2013 But I'm talking about function local data. The initialization of
- dennis luehring (7/32) May 16 2013 so youre example code isn't showing what you try to reach - makes it
- TommiT (4/6) May 16 2013 I should have said:
- Dicebot (1/1) May 16 2013 Against.
- Timothee Cour (10/10) May 16 2013 what's more fundamentally missing is ability to use ref on variables. DI...
- Kenji Hara (22/59) May 16 2013 Pure delegate and implicit conversion for unique expression should work.
- Timothee Cour (28/98) May 16 2013 simplified case:
- bearophile (5/14) May 16 2013 Once we have a tuple unpacking syntax, you return and assign to
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (25/40) May 16 2013 Until then, we have to define a local Tuple variable ('vars' below):
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.
May 16 2013
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") Am 16.05.2013 09:53, schrieb TommiT: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.
May 16 2013
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 } } On Thu, May 16, 2013 at 12:57 AM, dennis luehring <dl.soluz gmx.net> 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") Am 16.05.2013 09:53, schrieb TommiT: I'd like to make it easier to initialize function localimmutable/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.
May 16 2013
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.
May 16 2013
Am 16.05.2013 10:09, schrieb TommiT:On Thursday, 16 May 2013 at 07:59:20 UTC, dennis luehring wrote: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" featuredoesn'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.
May 16 2013
On Thursday, 16 May 2013 at 07:53:08 UTC, TommiT wrote: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; }();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 ?
May 16 2013
Am 16.05.2013 10:01, schrieb deadalnix:On Thursday, 16 May 2013 at 07:53:08 UTC, TommiT wrote:or even better - make them members of an helper class, with lookup methods and initialzation in ctor and put that into an const refI'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; }();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 ?
May 16 2013
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).
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: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 DavisThis 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).
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
On Thursday, May 16, 2013 11:32:39 TommiT wrote:On Thursday, 16 May 2013 at 08:31:27 UTC, Jonathan M Davis wrote:I mistyped. I meant static array. The variable isn't static. But yes, the problem is that the array is copied when the assignment is made.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.Except that what you're suggesting is effectively saying that you can write to a const variable, which violates the type system. It must be fully initialized in one go if it's const or immutable. Creating it as mutable and casting avoids this problem entirely and is very easy to do. I really don't see it as much of a problem. And by simply using a nested function, you not only are able to just initialize the variable in one go, but the code is cleaner because all of the mutation is encapsulated. - Jonathan M Davis
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
On 2013-05-16 09:53, TommiT wrote: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).Use a module constructor: static this () { } http://dlang.org/module.html#staticorder -- /Jacob Carlborg
May 16 2013
On Thursday, 16 May 2013 at 08:02:05 UTC, Jacob Carlborg wrote:Use a module constructor: static this () { } http://dlang.org/module.html#staticorderOn 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.
May 16 2013
Am 16.05.2013 10:14, schrieb TommiT:On Thursday, 16 May 2013 at 08:02:05 UTC, Jacob Carlborg wrote: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 accessUse a module constructor: static this () { } http://dlang.org/module.html#staticorderOn 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.
May 16 2013
On Thursday, 16 May 2013 at 07:53:08 UTC, TommiT wrote:string s = int__str[42]; // OK int__str[42] = "43" // ERROR: Can't modify constI should have said: int n = str__int["42"]; str__int["42"] = 43; // ERROR: Can't modify str__int
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
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
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
May 16 2013
On 05/16/2013 03:20 AM, bearophile wrote:TommiT:Until then, we have to define a local Tuple variable ('vars' below): import std.conv; import std.typecons; void foo(size_t N)() { auto init() { string[N] int__str; int[string] str__int; foreach (i; 0 .. N) { auto str = to!string(i); int__str[i] = str; str__int[str] = to!int(i); } return tuple(int__str, str__int); } const vars = init(); const string[N] int__str = vars[0]; const int[string] str__int = vars[1]; } void main() { foo!100(); } AliIf 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
May 16 2013