Re: Non-ugly ways to implement a 'static' class or namespace?

2023-01-28 Thread ProtectAndHide via Digitalmars-d-learn

On Wednesday, 25 January 2023 at 15:43:46 UTC, ryuukk_ wrote:


using static class and static function is not "OOP way" of 
doing things, it's a hack to mimic procedural style because 
Java doesn't have proper modules / scoping


mimicking the shortcomings of Java is a bad idea imo

D empowers you to write simple yet effective code, you should 
give it a try and embrace it


Classes (and this includes static classes) are 'one' means of 
encapsulation.


Encapsulation is related to, but independent of, object-oriented 
programming.


That is, you can do OOP without classes, and you can use classes 
and not do OOP.


So classes also 'empower' programmers ;-)

and btw. OOP also empowers programmers ;-)

There is no convincing argument that I have heard, ever, as to 
'the one correct way' to go about dividing a program into 
independent parts.


Re: hasUDA alternatives?

2023-01-28 Thread Hipreme via Digitalmars-d-learn

On Saturday, 28 January 2023 at 16:29:35 UTC, Anonymouse wrote:
I use `hasUDA`, `getUDAs` and `getSymbolsByUDA` fairly heavily 
in my project. dmd requires some 3.2Gb to compile it, a dub 
recompilation taking somewhere around 8-14 seconds, depending 
on the phase of the moon. It's not too bad, admittedly.


Stuff like this, naturally taken out of all context:

```
static if (isSerialisable!member)
{
import std.path : buildNormalizedPath;

static if (hasUDA!(this.tupleof[i], Resource))
{
member = 
buildNormalizedPath(state.settings.resourceDirectory, member);

}
else static if (hasUDA!(this.tupleof[i], Configuration))
{
member = 
buildNormalizedPath(state.settings.configDirectory, member);

}
}
```

```
private alias allEventHandlerFunctionsInModule =
Filter!(isSomeFunction, getSymbolsByUDA!(thisModule, 
IRCEventHandler));

```

```
enum isSetupFun(alias T) = (getUDAs!(T, 
IRCEventHandler)[0]._when == Timing.setup);
enum isEarlyFun(alias T) = (getUDAs!(T, 
IRCEventHandler)[0]._when == Timing.early);
enum isLateFun(alias T) = (getUDAs!(T, 
IRCEventHandler)[0]._when == Timing.late);
enum isCleanupFun(alias T) = (getUDAs!(T, 
IRCEventHandler)[0]._when == Timing.cleanup);
alias hasSpecialTiming = templateOr!(isSetupFun, isEarlyFun, 
isLateFun, isCleanupFun);

alias isNormalEventHandler = templateNot!hasSpecialTiming;

alias setupFuns = Filter!(isSetupFun, 
this.allEventHandlerFunctionsInModule);
alias earlyFuns = Filter!(isEarlyFun, 
this.allEventHandlerFunctionsInModule);
alias lateFuns = Filter!(isLateFun, 
this.allEventHandlerFunctionsInModule);
alias cleanupFuns = Filter!(isCleanupFun, 
this.allEventHandlerFunctionsInModule);
alias pluginFuns = Filter!(isNormalEventHandler, 
this.allEventHandlerFunctionsInModule);

```

If `hasUDA` and friends are so bad[1] [2] [3], what can I use 
instead?


I need them to work at compile-time. `hasUDA` just needs to 
evaluate to true or false, but for `getUDAs` and 
`getSymbolsByUDA` I need them to resolve to symbols (and not 
string names of symbols).


Do I have any alternatives?

[1]: 
https://forum.dlang.org/post/bwekufskjmknllapz...@forum.dlang.org

[2]: https://forum.dlang.org/post/tm02a6$nk3$1...@digitalmars.com
[3]: 
https://forum.dlang.org/post/nzlnwbcezwyopjfia...@forum.dlang.org




So, for that, having an exclude keyword would be nice. But for 
right now, I would like to check a better solution with you. 
Building my entire engine takes in LDC 250mb, in DMD I wasn't 
able to check but it seems to use really little.


From [2], FeepingCreature says that using udaIndex is better than 
using hasUDA and getUDAs.


getUDAs can be simply changed to `__traits(getAttributes, 
yourMemberHere)`.


Many std.traits things actually uses `Filter!()` which is a 
recursive template using `static if` + `AliasSeq`. Recursive 
templates are super heavy. In general, recursive functions always 
spells "slow" in any place.


The best thing to avoid in phobos are those recursive kinds, 
specially if you're using for too many places.


So, what can I do if I wish to construct a better filter? Well. 
Construct an array of indices to your filtered types instead of 
an AliasSeq. It is impossible to construct procedurally an 
AliasSeq without using recursive templates. That way you could 
iterate through those indices instead.


It is a little more manual work, but it is better on long run 
specially when you're not going to keep changing your reflection 
functions any soon



So, avoid Filter which seems to be your main bottleneck there. 
Specially because you will iterate all members many times. It is 
always best to do a single iteration and using the same data.


Your code seems to be analogous to doing:

```d
alias setupFuns = Filter!(isSetupFun, 
this.allEventHandlerFunctionsInModule);
alias earlyFuns = Filter!(isEarlyFun, 
this.allEventHandlerFunctionsInModule);


///Pseudo code expanded representation:


template setupFuns alias pred)
{
alias Filter = AliasSeq!();
static foreach (member; Module)
static if (pred!arg)
Filter = AliasSeq!(Filter, arg);
}
template earlyFuns(alias pred)
{
alias Filter = AliasSeq!();
static foreach (member; Module)
static if (pred!arg)
Filter = AliasSeq!(Filter, arg);
}
```

A better solution would be:

```d

static foreach(mem; __traits(allMembers, thisModule))
{
static if(is(typeof(__traits(getMember, thisModule, mem)) 
== EarlyFunc))
else static if(is(typeof(__traits(getMember, thisModule, 
mem)) == LateFunc))


}
```

That way, you would avoid: Recursive template executed a lot of 
times + you would use reflection once (iterate once vs iterate n 
times).


hasUDA alternatives?

2023-01-28 Thread Anonymouse via Digitalmars-d-learn
I use `hasUDA`, `getUDAs` and `getSymbolsByUDA` fairly heavily in 
my project. dmd requires some 3.2Gb to compile it, a dub 
recompilation taking somewhere around 8-14 seconds, depending on 
the phase of the moon. It's not too bad, admittedly.


Stuff like this, naturally taken out of all context:

```
static if (isSerialisable!member)
{
import std.path : buildNormalizedPath;

static if (hasUDA!(this.tupleof[i], Resource))
{
member = 
buildNormalizedPath(state.settings.resourceDirectory, member);

}
else static if (hasUDA!(this.tupleof[i], Configuration))
{
member = 
buildNormalizedPath(state.settings.configDirectory, member);

}
}
```

```
private alias allEventHandlerFunctionsInModule =
Filter!(isSomeFunction, getSymbolsByUDA!(thisModule, 
IRCEventHandler));

```

```
enum isSetupFun(alias T) = (getUDAs!(T, IRCEventHandler)[0]._when 
== Timing.setup);
enum isEarlyFun(alias T) = (getUDAs!(T, IRCEventHandler)[0]._when 
== Timing.early);
enum isLateFun(alias T) = (getUDAs!(T, IRCEventHandler)[0]._when 
== Timing.late);
enum isCleanupFun(alias T) = (getUDAs!(T, 
IRCEventHandler)[0]._when == Timing.cleanup);
alias hasSpecialTiming = templateOr!(isSetupFun, isEarlyFun, 
isLateFun, isCleanupFun);

alias isNormalEventHandler = templateNot!hasSpecialTiming;

alias setupFuns = Filter!(isSetupFun, 
this.allEventHandlerFunctionsInModule);
alias earlyFuns = Filter!(isEarlyFun, 
this.allEventHandlerFunctionsInModule);
alias lateFuns = Filter!(isLateFun, 
this.allEventHandlerFunctionsInModule);
alias cleanupFuns = Filter!(isCleanupFun, 
this.allEventHandlerFunctionsInModule);
alias pluginFuns = Filter!(isNormalEventHandler, 
this.allEventHandlerFunctionsInModule);

```

If `hasUDA` and friends are so bad[1] [2] [3], what can I use 
instead?


I need them to work at compile-time. `hasUDA` just needs to 
evaluate to true or false, but for `getUDAs` and 
`getSymbolsByUDA` I need them to resolve to symbols (and not 
string names of symbols).


Do I have any alternatives?

[1]: 
https://forum.dlang.org/post/bwekufskjmknllapz...@forum.dlang.org

[2]: https://forum.dlang.org/post/tm02a6$nk3$1...@digitalmars.com
[3]: 
https://forum.dlang.org/post/nzlnwbcezwyopjfia...@forum.dlang.org