Re: Fastest way to check using if identifier has already been defined, using static if or similar?

2020-06-04 Thread drathier via Digitalmars-d-learn

On Wednesday, 3 June 2020 at 09:03:22 UTC, drathier wrote:
I'm generating some code. Some of the generated types need to 
be overridden, so I define them manually at the top of the 
generated file. Then I need to guard against redefining the 
identifier (type/value/function) later on, in the generated 
code.


I'm currently using `static if (!__traits(compiles, thingy)) {` 
to avoid redefining things twice.


Of course the proper fix is to not generate code for the 
identifiers which are already manually defined, and not 
generate any `static if`s at all, but until then, is there a 
faster way than `static if (__traits(compiles, ...` to check if 
a type/value/function has already been defined?


This seems more complicated than I initially assumed. Is there a 
faster way if we separate the question to find just one of types, 
templates or top-level values at a time, into three different 
solutions? The definitions and static ifs are always always top 
level definitions/statements in my case.




Re: Fastest way to check using if identifier has already been defined, using static if or similar?

2020-06-04 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 4 June 2020 at 14:20:45 UTC, Q. Schroll wrote:


Little nitpicking, but D has many forms of string literals. 
Escaping is hard to read especially without syntax 
highlighting. Escaping to me is an old hack C did we shouldn't 
really use.


string exists(string s) {
return `__traits(compiles, { mixin("alias _ = ` ~ s ~ 
`;"); })`;

}

The _ as a name, to me, proves that a __traits(freshName), that 
returns a string that is distinct from every symbol name 
visible from the point it's defined,  would be useful in these 
occasions. Because if someone used _ as an identifier in a 
context where the `exisits` function is used, it might fail.


In the Lisp language family, this feature is called "gensym" 
(generate symbol). It is indeed quite useful to have when 
generating code.


I believe it was proposed at one point to add a special 
__GENSYM__ keyword, similar to the current __FILE__, __LINE__, 
__MODULE__, etc. that would evaluate to a unique identifier each 
time it was used. I'm not sure what became of that proposal. 
Maybe it needed a DIP and no one was available to write one?


Re: Fastest way to check using if identifier has already been defined, using static if or similar?

2020-06-04 Thread Stefan Koch via Digitalmars-d-learn

On Thursday, 4 June 2020 at 14:20:45 UTC, Q. Schroll wrote:

On Thursday, 4 June 2020 at 09:03:40 UTC, Simen Kjærås wrote:

string exists(string s) {
return "__traits(compiles, { mixin(\"alias _ = "~s~";\"); 
})";

}


Little nitpicking, but D has many forms of string literals. 
Escaping is hard to read especially without syntax 
highlighting. Escaping to me is an old hack C did we shouldn't 
really use.


string exists(string s) {
return `__traits(compiles, { mixin("alias _ = ` ~ s ~ 
`;"); })`;

}

The _ as a name, to me, proves that a __traits(freshName), that 
returns a string that is distinct from every symbol name 
visible from the point it's defined,  would be useful in these 
occasions. Because if someone used _ as an identifier in a 
context where the `exisits` function is used, it might fail.


Don't have a unique name facility now?
... I remember seeing one.
Could have been a mirage I guess.


Re: Fastest way to check using if identifier has already been defined, using static if or similar?

2020-06-04 Thread Q. Schroll via Digitalmars-d-learn

On Thursday, 4 June 2020 at 09:03:40 UTC, Simen Kjærås wrote:

string exists(string s) {
return "__traits(compiles, { mixin(\"alias _ = "~s~";\"); 
})";

}


Little nitpicking, but D has many forms of string literals. 
Escaping is hard to read especially without syntax highlighting. 
Escaping to me is an old hack C did we shouldn't really use.


string exists(string s) {
return `__traits(compiles, { mixin("alias _ = ` ~ s ~ 
`;"); })`;

}

The _ as a name, to me, proves that a __traits(freshName), that 
returns a string that is distinct from every symbol name visible 
from the point it's defined,  would be useful in these occasions. 
Because if someone used _ as an identifier in a context where the 
`exisits` function is used, it might fail.




Re: Fastest way to check using if identifier has already been defined, using static if or similar?

2020-06-04 Thread Simen Kjærås via Digitalmars-d-learn

On Wednesday, 3 June 2020 at 15:25:51 UTC, Paul Backus wrote:

On Wednesday, 3 June 2020 at 13:24:17 UTC, Basile B. wrote:
This is because the template parameter must be resolved to a 
valid symbol or type.

This version other version bypass the problem:

---
enum Exists(string s) = is(typeof(mixin(s)));

void main()
{
static if (!Exists!"foo")
int foo;
foo = 42;
}
---


Fails if the symbol in question is the name of a type.

struct Foo {}
enum Exists(string s) = is(typeof(mixin(s)));
static assert(Exists!"Foo"); // false

What you actually want is something like this:

enum Exists(string s) = __traits(compiles, { mixin("alias _ 
= ", s, ";"); });


And they both fail if the thing you refer to isn't available in 
the scope where Exists is defined. I believe this covers most 
cases, but there may very well be corner cases I haven't 
considered:


string exists(string s) {
return "__traits(compiles, { mixin(\"alias _ = "~s~";\"); })";
}

// Handles values:
int global;
unittest {
int local;
{
int outOfScope;
}
static assert(mixin("local".exists));
static assert(mixin("global".exists));
static assert(!mixin("outOfScope".exists));
}

// And types:
struct Global {}
unittest {
struct Local {}
{
struct OutOfScope;
}
static assert(mixin("Global".exists));
static assert(mixin("Local".exists));
static assert(!mixin("OutOfScope".exists));
}

// But not expressions:
static assert(!mixin("1+2".exists));
// Correctly fails for missing declarations:
static assert(!mixin("nowhere".exists));

Like Stefan said though, we're quite a bit off from the original 
request - the above certainly shouldn't be faster than drathier's 
original code. The only advantage I see is that it might read a 
little clearer.


--
  Simen


Re: Fastest way to check using if identifier has already been defined, using static if or similar?

2020-06-03 Thread Stefan Koch via Digitalmars-d-learn

On Wednesday, 3 June 2020 at 09:39:34 UTC, Basile B. wrote:

On Wednesday, 3 June 2020 at 09:03:22 UTC, drathier wrote:

[...]


You can use this template:

  enum Exists(alias T) = is(typeof(T));

I don't know if there's a faster way bu this technic is used, 
notatbly in phobos, to workaroud issues of double declaration 
in `static foreach`


Please don't promote templates like this as long as they are not 
really zero-cost.

They don't add much to compile time granted.
But Barnacles.



Re: Fastest way to check using if identifier has already been defined, using static if or similar?

2020-06-03 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 3 June 2020 at 13:24:17 UTC, Basile B. wrote:
This is because the template parameter must be resolved to a 
valid symbol or type.

This version other version bypass the problem:

---
enum Exists(string s) = is(typeof(mixin(s)));

void main()
{
static if (!Exists!"foo")
int foo;
foo = 42;
}
---


Fails if the symbol in question is the name of a type.

struct Foo {}
enum Exists(string s) = is(typeof(mixin(s)));
static assert(Exists!"Foo"); // false

What you actually want is something like this:

enum Exists(string s) = __traits(compiles, { mixin("alias _ = 
", s, ";"); });


Re: Fastest way to check using if identifier has already been defined, using static if or similar?

2020-06-03 Thread Basile B. via Digitalmars-d-learn

On Wednesday, 3 June 2020 at 10:24:44 UTC, Simen Kjærås wrote:

On Wednesday, 3 June 2020 at 09:39:34 UTC, Basile B. wrote:

You can use this template:

  enum Exists(alias T) = is(typeof(T));

I don't know if there's a faster way bu this technic is used, 
notatbly in phobos, to workaroud issues of double declaration 
in `static foreach`


enum Exists(alias T) = is(typeof(T));
static assert(!Exists!bar); // undefined identifier bar

--
  Simen


This is because the template parameter must be resolved to a 
valid symbol or type.

This version other version bypass the problem:

---
enum Exists(string s) = is(typeof(mixin(s)));

void main()
{
static if (!Exists!"foo")
int foo;
foo = 42;
}
---


Re: Fastest way to check using if identifier has already been defined, using static if or similar?

2020-06-03 Thread Simen Kjærås via Digitalmars-d-learn

On Wednesday, 3 June 2020 at 09:39:34 UTC, Basile B. wrote:

You can use this template:

  enum Exists(alias T) = is(typeof(T));

I don't know if there's a faster way bu this technic is used, 
notatbly in phobos, to workaroud issues of double declaration 
in `static foreach`


enum Exists(alias T) = is(typeof(T));
static assert(!Exists!bar); // undefined identifier bar

--
  Simen


Re: Fastest way to check using if identifier has already been defined, using static if or similar?

2020-06-03 Thread Basile B. via Digitalmars-d-learn

On Wednesday, 3 June 2020 at 09:03:22 UTC, drathier wrote:
I'm generating some code. Some of the generated types need to 
be overridden, so I define them manually at the top of the 
generated file. Then I need to guard against redefining the 
identifier (type/value/function) later on, in the generated 
code.


I'm currently using `static if (!__traits(compiles, thingy)) {` 
to avoid redefining things twice.


Of course the proper fix is to not generate code for the 
identifiers which are already manually defined, and not 
generate any `static if`s at all, but until then, is there a 
faster way than `static if (__traits(compiles, ...` to check if 
a type/value/function has already been defined?


You can use this template:

  enum Exists(alias T) = is(typeof(T));

I don't know if there's a faster way bu this technic is used, 
notatbly in phobos, to workaroud issues of double declaration in 
`static foreach`


Fastest way to check using if identifier has already been defined, using static if or similar?

2020-06-03 Thread drathier via Digitalmars-d-learn
I'm generating some code. Some of the generated types need to be 
overridden, so I define them manually at the top of the generated 
file. Then I need to guard against redefining the identifier 
(type/value/function) later on, in the generated code.


I'm currently using `static if (!__traits(compiles, thingy)) {` 
to avoid redefining things twice.


Of course the proper fix is to not generate code for the 
identifiers which are already manually defined, and not generate 
any `static if`s at all, but until then, is there a faster way 
than `static if (__traits(compiles, ...` to check if a 
type/value/function has already been defined?