Thread overview
Generating unique identifiers at compile time
Jun 09, 2022
JG
Jun 09, 2022
user1234
Jun 10, 2022
bauss
Jun 12, 2022
JG
Jun 13, 2022
user1234
Jun 13, 2022
user1234
Jun 12, 2022
Paul Backus
Jun 12, 2022
JG
June 09, 2022

Hi,

As an experiment I have implemented the following kind of pattern matching
(by parsing the part of the string before '=').

struct S {
int x;
int y;
}

struct T {
    int w;
    S s;
}
void main()
{
    mixin(matchAssign(q{auto T(first,S(second,third)) = T(1,S(2,3));}));
    first.writeln;  // 1
    second.writeln; // 2
    third.writeln;  // 3
}

In doing so I wanted to produce unique identifiers (something like gensym in racket.) I did this in a very hacky way:

auto hopefullyUniqueName(size_t n, size_t line=__LINE__) {
    return format!"____________________________var___________________________%s%s"(n,line);
}

where I pass in the hash of the right hand side in the assignment in place of n.

Is there some way to ask the compiler for a unique name or a better way of achieving this?

June 09, 2022

On Thursday, 9 June 2022 at 21:20:27 UTC, JG wrote:

>

Hi,

As an experiment I have implemented the following kind of pattern matching
(by parsing the part of the string before '=').

struct S {
int x;
int y;
}

struct T {
    int w;
    S s;
}
void main()
{
    mixin(matchAssign(q{auto T(first,S(second,third)) = T(1,S(2,3));}));
    first.writeln;  // 1
    second.writeln; // 2
    third.writeln;  // 3
}

In doing so I wanted to produce unique identifiers (something like gensym in racket.) I did this in a very hacky way:

auto hopefullyUniqueName(size_t n, size_t line=__LINE__) {
    return format!"____________________________var___________________________%s%s"(n,line);
}

where I pass in the hash of the right hand side in the assignment in place of n.

Is there some way to ask the compiler for a unique name or a better way of achieving this?

No, for now there if there are other ways they are as hacky as yours.

The compiler usually uses a global counter to generate temporaries.
There's been attempts to expose it, exactly so that users can generate unique names, but that did not found its path in the compiler.

June 10, 2022

On Thursday, 9 June 2022 at 23:50:10 UTC, user1234 wrote:

>

There's been attempts to expose it, exactly so that users can generate unique names, but that did not found its path in the compiler.

You can generate unique names actually by using CTFE RNG, so it's not really necessary to have it exposed to achieve that.

See my hacky example of hidden class members here:

https://forum.dlang.org/thread/siczwzlbpikwlevviwxt@forum.dlang.org

June 12, 2022

On Friday, 10 June 2022 at 06:17:54 UTC, bauss wrote:

>

On Thursday, 9 June 2022 at 23:50:10 UTC, user1234 wrote:

>

There's been attempts to expose it, exactly so that users can generate unique names, but that did not found its path in the compiler.

You can generate unique names actually by using CTFE RNG, so it's not really necessary to have it exposed to achieve that.

See my hacky example of hidden class members here:

https://forum.dlang.org/thread/siczwzlbpikwlevviwxt@forum.dlang.org

Thanks for the answers. In my particular I found a way to generate
a new depending on the the left hand side.

June 12, 2022

On Thursday, 9 June 2022 at 21:20:27 UTC, JG wrote:

>

In doing so I wanted to produce unique identifiers (something like gensym in racket.) I did this in a very hacky way:
[...]
Is there some way to ask the compiler for a unique name or a better way of achieving this?

Here's a gensym implementation I came up with a while back:

enum gensym = q{"_gensym" ~ __traits(identifier, {})["__lambda".length .. $]};

// Works multiple times on the same line
pragma(msg, mixin(gensym)); pragma(msg, mixin(gensym));

This takes advantage of the fact that the compiler generates a unique identifier for every lambda function it encounters. While you can't actually use those identifiers in your code, they are visible in error messages and can be accessed via __traits(identifier).

June 12, 2022

On Sunday, 12 June 2022 at 18:45:27 UTC, Paul Backus wrote:

>

On Thursday, 9 June 2022 at 21:20:27 UTC, JG wrote:

>

[...]
[...]
[...]

Here's a gensym implementation I came up with a while back:

enum gensym = q{"_gensym" ~ __traits(identifier, {})["__lambda".length .. $]};

// Works multiple times on the same line
pragma(msg, mixin(gensym)); pragma(msg, mixin(gensym));

This takes advantage of the fact that the compiler generates a unique identifier for every lambda function it encounters. While you can't actually use those identifiers in your code, they are visible in error messages and can be accessed via __traits(identifier).

Hi,

This is great thanks.

June 13, 2022

On Thursday, 9 June 2022 at 23:50:10 UTC, user1234 wrote:

>

On Thursday, 9 June 2022 at 21:20:27 UTC, JG wrote:

>

[...]

No, for now there if there are other ways they are as hacky as yours.

The compiler usually uses a global counter to generate temporaries.
There's been attempts to expose it, exactly so that users can generate unique names, but that did not found its path in the compiler.

Here's another one. That's nice if people are able to find tricks but there's a need to have a clean way to do that. i.e language feature.

June 13, 2022

On Monday, 13 June 2022 at 07:38:54 UTC, user1234 wrote:

>

On Thursday, 9 June 2022 at 23:50:10 UTC, user1234 wrote:

>

On Thursday, 9 June 2022 at 21:20:27 UTC, JG wrote:

>

[...]

No, for now there if there are other ways they are as hacky as yours.

The compiler usually uses a global counter to generate temporaries.
There's been attempts to expose it, exactly so that users can generate unique names, but that did not found its path in the compiler.

Here's another one. That's nice if people are able to find tricks but there's a need to have a clean way to do that. i.e language feature.

Damnit, forgot the link