|
> b!(c.d)(a) The template parameter after a ! without parentheses is always 1 token, so it's never one of the first two interpretations. Furthermore, the point is that often when writing generic code, you're not supposed to care what the `.d` means specifically. For example, an `InputRange` is defined to have `.front`, `.empty` and `.popFront` properties. Is `.empty` a member variable, function, or constant? Doesn't matter, as long as it results in a boolean. This does require some getting used to. A common question from newcomers is how to explicitly spell out the type in a situation like this: import std.algorithm;
void main()
{
auto x = [10, 20, 30].map!(x => x*2);
}
The answer is: you cannot! You know it's an `InputRange`, so you can access `.front`, `.empty`, `.popFront`, and pass it to range functions, but it's not a simple type like `int[]`.While it's flexible, generic code is also complex. Many D standard library functions don't take a simple `string`, but a 'generic input range of a code unit'. (UTF-8, UTF-16, UTF-32). The resulting template machinery that this spawns is not pleasant to work with, so I understand your concern. In my own D code, I often use regular arrays, foreach loops and if-statements instead of ranges, map and filter etc. |