digitalmars.D.learn - Is it possible to add items to the arrays and hashes at compile time?
- Dennis Ritchie (6/6) Jun 07 2015 Does D the ability to add items to arrays and hashes at compile
- Nicholas Wilson (8/14) Jun 07 2015 try using a pure function + static e.g.
- Nicholas Wilson (2/19) Jun 07 2015 or enum
- H. S. Teoh via Digitalmars-d-learn (6/29) Jun 07 2015 Using an enum for an array or hash is usually a bad idea, because it
- Dennis Ritchie (2/3) Jun 07 2015 I suspect that enum can not add elements to the array.
- Dennis Ritchie (5/13) Jun 07 2015 static int[][int][int] hash;
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (54/69) Jun 07 2015 /* Some function that generates an AA */
- Dennis Ritchie (50/51) Jun 09 2015 Thanks. Beautiful code, but I want a little more :)
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (15/17) Jun 09 2015 It is possible but not exactly as you wrote. In other words, it is not
- Dennis Ritchie (29/33) Jun 09 2015 Thanks. It turns out I can do this:
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (10/15) Jun 10 2015 My phrasing was off: By definition, initialization happens once. :) What...
- Dennis Ritchie (11/20) Jun 10 2015 I understand your phrase :) I don't understand why the variables
- anonymous (3/6) Jun 10 2015 Sounds like the halting problem. So, no, generally this is not
- Dennis Ritchie (3/10) Jun 10 2015 Thanks. I had never heard of the halting problem. This is exactly
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (21/24) Jun 10 2015 I am not a compiler writer but I assume if a variable is not a
- Dennis Ritchie (12/27) Jun 10 2015 Unfortunately, the halting problem says that the analyzer does
Does D the ability to add items to arrays and hashes at compile time? For example, how do I do it in compile time?: int[][int][int] hash; hash[4][6] ~= [34, 65]; hash[5][7] ~= [4, 78, 21];
Jun 07 2015
On Sunday, 7 June 2015 at 12:30:12 UTC, Dennis Ritchie wrote:Does D the ability to add items to arrays and hashes at compile time? For example, how do I do it in compile time?: int[][int][int] hash; hash[4][6] ~= [34, 65]; hash[5][7] ~= [4, 78, 21];try using a pure function + static e.g. int[][int][int] somePureDefaultHash() pure { ... //initialise it here } ... static hash = somePureDefaultHash();
Jun 07 2015
On Sunday, 7 June 2015 at 12:42:12 UTC, Nicholas Wilson wrote:On Sunday, 7 June 2015 at 12:30:12 UTC, Dennis Ritchie wrote:or enumDoes D the ability to add items to arrays and hashes at compile time? For example, how do I do it in compile time?: int[][int][int] hash; hash[4][6] ~= [34, 65]; hash[5][7] ~= [4, 78, 21];try using a pure function + static e.g. int[][int][int] somePureDefaultHash() pure { ... //initialise it here } ... static hash = somePureDefaultHash();
Jun 07 2015
On Sun, Jun 07, 2015 at 12:43:16PM +0000, Nicholas Wilson via Digitalmars-d-learn wrote:On Sunday, 7 June 2015 at 12:42:12 UTC, Nicholas Wilson wrote:Using an enum for an array or hash is usually a bad idea, because it causes a runtime allocation per reference to that symbol. T -- "I suspect the best way to deal with procrastination is to put off the procrastination itself until later. I've been meaning to try this, but haven't gotten around to it yet. " -- swrOn Sunday, 7 June 2015 at 12:30:12 UTC, Dennis Ritchie wrote:or enumDoes D the ability to add items to arrays and hashes at compile time? For example, how do I do it in compile time?: int[][int][int] hash; hash[4][6] ~= [34, 65]; hash[5][7] ~= [4, 78, 21];try using a pure function + static e.g. int[][int][int] somePureDefaultHash() pure { ... //initialise it here } ... static hash = somePureDefaultHash();
Jun 07 2015
On Sunday, 7 June 2015 at 12:43:17 UTC, Nicholas Wilson wrote:or enumI suspect that enum can not add elements to the array.
Jun 07 2015
On Sunday, 7 June 2015 at 12:42:12 UTC, Nicholas Wilson wrote:On Sunday, 7 June 2015 at 12:30:12 UTC, Dennis Ritchie wrote: try using a pure function + static e.g. int[][int][int] somePureDefaultHash() pure { ... //initialise it here } ... static hash = somePureDefaultHash();static int[][int][int] hash; hash[4][6] ~= [34, 65]; static if (!!(4 in hash)) {} // Error: static variable hash cannot be read at compile time
Jun 07 2015
On 06/07/2015 05:56 AM, Dennis Ritchie wrote:On Sunday, 7 June 2015 at 12:42:12 UTC, Nicholas Wilson wrote:/* Some function that generates an AA */ int[][int][int] initHash(int i) { /* It is nice to see that this function is not called at run time */ if (!__ctfe) { import std.stdio; writefln("%s is called at run time", __FUNCTION__); } return [i : [ i : [i, i] ] ]; } /* Question: Is there a function to merge two AAs? */ int[][int][int] merge()(int[][int][int][] hashes...) { /* It is nice to see that this function is not called at run time */ if (!__ctfe) { import std.stdio; writefln("%s is called at run time", __FUNCTION__); } int[][int][int] result; foreach (hash; hashes) { foreach (key, value; hash) { result[key] = value; } } return result; } /* These three are generated at compile time */ enum firstPart = initHash(1); enum secondPart = initHash(2); enum int[][int][int] ctHash = merge(firstPart, secondPart); /* Although ctHash is useful by itself, as H. S. Teoh said, every * reference to that AA at run time will generate a new AA. So, we * better refer to it just once. * * Luckily, as the __ctfe expressions above prove, the initialization * happens only once at compile time. I guess the memory layout of * 'ctHash' is simply copied to 'hash' below. */ int[][int][int] hash; static this() { hash = ctHash; } void main() { import std.stdio; writeln(hash); /* This is to see that the slice elements are not generated at * every reference. (It is good that .ptr value of each member * slice is the same.) */ writeln(hash[1][1].ptr, ' ', hash[2][2].ptr); writeln(hash[1][1].ptr, ' ', hash[2][2].ptr); } AliOn Sunday, 7 June 2015 at 12:30:12 UTC, Dennis Ritchie wrote: try using a pure function + static e.g. int[][int][int] somePureDefaultHash() pure { ... //initialise it here } ... static hash = somePureDefaultHash();static int[][int][int] hash; hash[4][6] ~= [34, 65]; static if (!!(4 in hash)) {} // Error: static variable hash cannot be read at compile time
Jun 07 2015
On Sunday, 7 June 2015 at 15:20:17 UTC, Ali Çehreli wrote:/* Some function that generates an AA */Thanks. Beautiful code, but I want a little more :) /* Some function that generates an AA */ int[][int][int] initHash(int i) { /* It is nice to see that this function is not called at run time */ if (!__ctfe) { import std.stdio; writefln("%s is called at run time", __FUNCTION__); } return [i : [ i : [i, i] ] ]; } /* Question: Is there a function to merge two AAs? */ int[][int][int] merge(Hash)(Hash[] hashes...) { /* It is nice to see that this function is not called at run time */ if (!__ctfe) { import std.stdio; writefln("%s is called at run time", __FUNCTION__); } int[][int][int] result; foreach (hash; hashes) { foreach (key, value; hash) { result[key] = value; } } return result; } /* These three are generated at compile time */ enum firstPart = initHash(1); enum secondPart = initHash(2); enum int[][int][int] ctHash = merge(firstPart, secondPart); void main() { import std.stdio; static if (!(4 in ctHash)) {{ // ... }} ctHash[4][4] ~= [4, 4]; // I want this to work at compile time :) // Possible? static if (!!(4 in ctHash)) {{ // ... }} }
Jun 09 2015
On 06/09/2015 06:53 PM, Dennis Ritchie wrote:ctHash[4][4] ~= [4, 4]; // I want this to work at compile time :) // Possible?It is possible but not exactly as you wrote. In other words, it is not as flexible. The way I understand it and the way it makes sense to me, :) variables that are generated at compile time can be initialized only once. It is not possible after initialization. However, the initialization of the variable can be as complex as needed: enum int[][int][int] ctHash = init_ctHash(); int[][int][int] init_ctHash(){ auto result = merge(firstPart, secondPart); result[4] = [4 : [4, 4 ]]; return result; } (I couldn't get ctHash[4][4] to work; so I changed the code like above.) Ali
Jun 09 2015
On Wednesday, 10 June 2015 at 03:38:32 UTC, Ali Çehreli wrote:The way I understand it and the way it makes sense to me, :) variables that are generated at compile time can be initialized only once. It is not possible after initialization. However, the initialization of the variable can be as complex as needed:Thanks. It turns out I can do this: import std.stdio; auto merge(Hashes)(Hashes[] hashes...) { int[][int][int] result; foreach (hash; hashes) { foreach (key, value; hash) { result[key] = value; } } return result; } enum firstPart = [1 : [ 1 : [1, 1] ] ]; enum secondPart = [2 : [ 2 : [2, 2] ] ]; int[][int][int] init_ctHash(int i) { auto result = merge(firstPart, secondPart); result[i] = [ i : [i, i] ]; return result; } void main() { enum int[][int][int] ctHash = init_ctHash(5); enum t = merge(ctHash, init_ctHash(6)); writeln(t); } But I can not do so: enum int[][int][int] ctHash = init_ctHash(5); ctHash = merge(ctHash, init_ctHash(6)); I have a question: why variables may not be initialized more than once? Why can't they to resave at compile time?
Jun 09 2015
On 06/09/2015 09:36 PM, Dennis Ritchie wrote:But I can not do so: enum int[][int][int] ctHash = init_ctHash(5); ctHash = merge(ctHash, init_ctHash(6)); I have a question: why variables may not be initialized more than once? Why can't they to resave at compile time?My phrasing was off: By definition, initialization happens once. :) What I meant is, once initialized, a compile-time variable cannot be reassigned. The reason is, to effect compile time evaluation, one needs to use 'enum' (or 'static const') but 'enum' is a literal, i.e. it cannot be modified. As I've shown, it is possible to use an expression that will be used as the value of the compile-time variable. As long as it is evaluable at compile time, the expression can be arbitrarily complex. Ali
Jun 10 2015
On Wednesday, 10 June 2015 at 07:15:26 UTC, Ali Çehreli wrote:My phrasing was off: By definition, initialization happens once. :) What I meant is, once initialized, a compile-time variable cannot be reassigned. The reason is, to effect compile time evaluation, one needs to use 'enum' (or 'static const') but 'enum' is a literal, i.e. it cannot be modified. As I've shown, it is possible to use an expression that will be used as the value of the compile-time variable. As long as it is evaluable at compile time, the expression can be arbitrarily complex.I understand your phrase :) I don't understand why the variables at compile time cannot be reassigned. I.e. why can't we use `int` instead of `enum` or `immutable`? Isnt it possible to come up with the interpreter compile-time, which will determine the operating time of the program at runtime at compile time. And if this time is small, it is possible to reassign variables at compile time more than once. Maybe it's something out of science fiction, but still. Is it possible somehow to create a more complex compilation process, which can reassign variables more than once?
Jun 10 2015
On Wednesday, 10 June 2015 at 17:00:34 UTC, Dennis Ritchie wrote:Isnt it possible to come up with the interpreter compile-time, which will determine the operating time of the program at runtime at compile time.Sounds like the halting problem. So, no, generally this is not possible.
Jun 10 2015
On Wednesday, 10 June 2015 at 17:13:34 UTC, anonymous wrote:On Wednesday, 10 June 2015 at 17:00:34 UTC, Dennis Ritchie wrote:Thanks. I had never heard of the halting problem. This is exactly what I wanted to know.Isnt it possible to come up with the interpreter compile-time, which will determine the operating time of the program at runtime at compile time.Sounds like the halting problem. So, no, generally this is not possible.
Jun 10 2015
On 06/10/2015 10:00 AM, Dennis Ritchie wrote:Is it possible somehow to create a more complex compilation process, which can reassign variables more than once?I am not a compiler writer but I assume if a variable is not a compile-time expression, then the compiler generates code that makes it possible to initialize it at run time and modify it if mutable: int i = argc; // ... ++i; On the other hand, if it's a manifest constant (enum, const static, etc.) then by definition it cannot be mutated. If we allowed mutation of compile-time expressions, then we would have a complicated language. enum i = 42; enum j = foo(i); // Did foo() use 42 or 43? i = 43; enum k = foo(i); // Did foo() use 42 or 43? How can an enum value be changed? I find the above confusing. The great thing about D's CTFE is that we can use arbitrarily complex expressions as long as they are available at compile time. For example, it is possible to make 'i' above a foreach loop variable and call foo() with different values. What is your use case? I feel like it can be solved by other means. Ali
Jun 10 2015
On Wednesday, 10 June 2015 at 17:43:36 UTC, Ali Çehreli wrote:On the other hand, if it's a manifest constant (enum, const static, etc.) then by definition it cannot be mutated. If we allowed mutation of compile-time expressions, then we would have a complicated language.Unfortunately, the halting problem says that the analyzer does not exist. Although I don't believe it!enum i = 42; enum j = foo(i); // Did foo() use 42 or 43? i = 43; enum k = foo(i); // Did foo() use 42 or 43? How can an enum value be changed? I find the above confusing.So in fact, if `int` is evaluated at compile time, then we won't need constants or enums. Because they almost would not make sense. Although the issues associated with immutability, complex, I think they can be solved differently.The great thing about D's CTFE is that we can use arbitrarily complex expressions as long as they are available at compile time. For example, it is possible to make 'i' above a foreach loop variable and call foo() with different values.There is nothing great. Everything is based on constexpr of C++. I want something more revolutionary :)What is your use case? I feel like it can be solved by other means.There is no precedent special :) I just want to know more about the possibilities of D and the possibility of its compiler. D made me a terrible interest in compilers :)
Jun 10 2015