Recommendations on avoiding range pipeline type hell
SealabJaster
sealabjaster at gmail.com
Sun May 16 10:10:54 UTC 2021
On Sunday, 16 May 2021 at 09:55:31 UTC, Chris Piker wrote:
> Maybe that's eminently reasonable to those with deep knowledge,
> but it seems crazy to a new D programmer. It breaks a general
> assumption about programming when copying and pasting a
> definition yields two things that aren't the same type. (except
> in rare cases like SQL where null != null.)
It's due to a quirk with passing lambdas as template arguments.
Each lambda is actually separated into its own function.
It's kind of hard to explain, but examine this code:
```d
// runnable version: https://run.dlang.io/is/NbU3iT
struct S(alias Func)
{
pragma(msg, __traits(identifier, Func));
}
int func(int a)
{
return a*2;
}
void main()
{
auto a = S!(a => a*2)();
auto b = S!(a => a*2)();
// Comment above. Then uncomment below for a working version.
/*
auto a = S!func();
auto b = S!func();
*/
pragma(msg, typeof(a));
pragma(msg, typeof(b));
a = b;
}
```
In its given state, this is the following output:
```
__lambda1
__lambda3
S!((a) => a * 2)
S!((a) => a * 2)
onlineapp.d(24): Error: cannot implicitly convert expression `b`
of type `onlineapp.main.S!((a) => a * 2)` to
`onlineapp.main.S!((a) => a * 2)`
```
So while `typeof(a)` and `typeof(b)` **look** like they are the
same, in actuality you can see that `auto a` uses `__lambda1`,
whereas `auto b` uses `__lambda3`.
This means that, even though visually they should be equal, they
are in fact two entirely separate types.
So if you had a nested `Result` struct, it'd look more like
`S!__lambda1.Result` and `S!__lambda3.Result`, instead of just
`S!IDENTICAL_LAMBDA.Result`.
Confusing, I know...
So if we change this to using a non-lambda function (doing the
commenting/uncommenting as mentioned in the code) then we get
successful output:
```
func
S!(func)
S!(func)
```
p.s. I love that you can debug D within D.
More information about the Digitalmars-d-learn
mailing list