Jump to page: 1 2
Thread overview
Is it possible to add items to the arrays and hashes at compile time?
Jun 07, 2015
Dennis Ritchie
Jun 07, 2015
Nicholas Wilson
Jun 07, 2015
Nicholas Wilson
Jun 07, 2015
H. S. Teoh
Jun 07, 2015
Dennis Ritchie
Jun 07, 2015
Dennis Ritchie
Jun 07, 2015
Ali Çehreli
Jun 10, 2015
Dennis Ritchie
Jun 10, 2015
Ali Çehreli
Jun 10, 2015
Dennis Ritchie
Jun 10, 2015
Ali Çehreli
Jun 10, 2015
Dennis Ritchie
Jun 10, 2015
anonymous
Jun 10, 2015
Dennis Ritchie
Jun 10, 2015
Ali Çehreli
Jun 10, 2015
Dennis Ritchie
June 07, 2015
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];
June 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();
June 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:
>> 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();

or enum
June 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:
> >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();
> 
> or enum

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. " -- swr
June 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
June 07, 2015
On Sunday, 7 June 2015 at 12:43:17 UTC, Nicholas Wilson wrote:
> or enum

I suspect that enum can not add elements to the array.
June 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:
>> 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

/* 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);
}

Ali

June 10, 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)) {{
		// ...
	}}
}
June 10, 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

June 10, 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?
« First   ‹ Prev
1 2