|
|
|
|
|
by jhhh
1662 days ago
|
|
I don't disagree that it can be useful (eg. from one of the other projects mentioned in the thread: https://github.com/Netflix/vectorflow/blob/master/src/vector...), and I definitely saw plenty of people that liked it. I think it existed in the same realm as a feature like lisp macros which are incredibly useful but when overused can turn the code into an inscrutable mess. The question for me was always how much the community would use or overuse them. When talking with other people it seemed like their own use of UFCS was obvious, but then again they wrote the code so of course they were going to understand it. Without knowing any of the associated types and members how many interpretations could the prior expression 'a.b!c.d' have with UFCS and parens-less calling conventions (and any other feature that might contribute to different semantics)? b!(c.d)(a)
b!(d(c))(a)
d(b!c(a))
d(a.b!c)
Might be more? Don't get me wrong I see the benefit. The vectorflow example I think is a good use case thought because it allows a more natural conceptualization of object -> member access -> conversion rather than having to call to!ulong(W.length) which forces the reader to start with the (pending) conversion. You get this same dataflow/conceptualization benefit in threading macros in clojure (->, ->>, etc).Anyway, thank you for all the work you've done. |
|
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:
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.