Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?

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

On Thursday, 4 June 2020 at 19:42:57 UTC, mw wrote:

On Thursday, 4 June 2020 at 18:42:05 UTC, H. S. Teoh wrote:
TBH, whenever I run into a diamond inheritance problem or 
similar, my first reaction is, I'm using the wrong tool for

   ^^

Haha, it's also because most of the populate OO languages didn't 
solve the diamond problem, and made the multiple inheritance hard 
to use in such situation, that's how the programmers learnt this 
"first reaction" from past bad experience.


Conversely, if all the OO languages solved the diamond problem 
cleanly from the very start, the programmers will never learn 
such reaction.




Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?

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

On Thursday, 4 June 2020 at 18:42:05 UTC, H. S. Teoh wrote:
TBH, whenever I run into a diamond inheritance problem or 
similar, my first reaction is, I'm using the wrong tool for 
modelling my data; I should be using some kind of 
component-based system instead of OO inheritance.


I have no problem with whatever modelling technique the 
programmer want to choose.


What I hate to see is: if a language does provide the OO 
mechanism, but having some loop-holes that causes trouble for the 
programmer who choose to use it. Esp. when these loop-holes are 
crept in after the language's initial design.


(For example, I won't discuss multiple inheritance on a C forum, 
it's not that language designed for.)




Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?

2020-06-04 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jun 04, 2020 at 06:09:35PM +, mw via Digitalmars-d-learn wrote:
[...]
> --
> class Person : NameI, AddrI {
>   mixin NameT!Person rename equals as name_equals;
>   mixin AddrT!Person rename equals as addr_equals;
> 
>   bool equals(Person other) {
> return this.name_equals(other) &&
>this.addr_equlas(other);
>   }
> }
> --

TBH, whenever I run into a diamond inheritance problem or similar, my
first reaction is, I'm using the wrong tool for modelling my data; I
should be using some kind of component-based system instead of OO
inheritance.

Nowadays I rarely use OO-style inheritance for data modelling anymore;
it's still useful for rare cases where a straight hierarchy makes sense
(traditional GUI widgets, for example, or parse trees), but for complex
modelling I just stop pretending that there's a direct mapping from
problem domain to language constructs, and instead build containers that
have arbitrary component combinations as an infrastructure instead.

Recently I've been dabbling in ECS (entity-component-system) adaptations
from gamedev: the system part is not useful to me, but the idea behind
entity-component storage is very useful for modelling complex data, much
more suitable than traditional OO inheritance IMO.


T

-- 
I am Ohm of Borg. Resistance is voltage over current.


Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?

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

On Sunday, 31 May 2020 at 06:28:11 UTC, mw wrote:

This is better, ... but it breaks std.traits:

void main() {
  auto fields = FieldNameTuple!(Point);
  writeln(fields);
}

$ ./b
varvarvar

And normally, we cannot define 2 fields with different types:

class P {
  int x;
  double x;  // b.d(45): Error: variable b.P.x conflicts with 
variable b.P.x at b.d(44)

}

With the above template we somehow tricked the compiler to be 
able to do this?


Is this a loop-hole we should file a bug?



This is related to D's silent crept-in multiple inheritance 
problem, a solution via language improvement is here:


https://forum.dlang.org/post/lsnhqdoyatkzbzqbs...@forum.dlang.org


I'd imagine something like this:

--
class Person : NameI, AddrI {
  mixin NameT!Person rename equals as name_equals;
  mixin AddrT!Person rename equals as addr_equals;

  bool equals(Person other) {
return this.name_equals(other) &&
   this.addr_equlas(other);
  }
}
--



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: Is there a list of things which are slow to compile?

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

On Wednesday, 3 June 2020 at 17:02:35 UTC, H. S. Teoh wrote:
On Wed, Jun 03, 2020 at 09:36:52AM +, drathier via 
Digitalmars-d-learn wrote:
I'm wondering if there's a place that lists things which are 
slower/faster to compile? DMD is pretty famed for compiling 
quickly, but I'm not seeing particularly high speed at all, 
and I want to fix that.


The two usual culprits are:
- Recursive/chained templates
- Excessive CTFE

...

T


Thanks for the comprehensive answer!

I'm not using CTFE at all, because as you thought, Variants 
aren't supported in CTFE. I had to go out of my way to avoid CTFE 
running, since it crashes on Variants. I'm not using UFCS, and 
the long identifiers I was talking about are like 50 characters 
long, from mangling package name + module name + variable name 
together in the source language.


I'm guessing it's mainly templates from my code gen then, and 
there's not much I can do about that; I'm doing code gen from a 
functional language where polymorphism is literally everywhere, 
and so are templates then.


Regarding std.format, std.regex and such, would it be possible to 
put those into their own package or something, so `dub` doesn't 
rebuild them every time? It feels like that'd save a lot of time.


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