On 3 September 2016 at 11:09, Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote: > > First solution: > > module bob; > struct S { > void f(); > }
This is my current workaround. I'm not happy with it at all. UFCS exists for a reason. > Second solution: > > module user_code; > import bob, joe; > import myalgorithm; > > mixin myalgorithm.test!S; > mixin myalgorithm.test!T; > > void main() > { > test(S.init); > test(T.init); > } You're not serious, right? I just want to call a function... functions should be functions, not mixin templates! > Third solution: > > module myalgorithm; > void test(M,T)(T t) > { > M.f(t); > } > > module user_code; > import bob, joe; > import myalgorithm; > > void main() > { > test!bob(S.init); > test!joe(T.init); > } Another crazy workaround. Users should not be expected to manually pass scope's around the place to perform a name lookup. Try and explain that to a normal programmer. > Fourth solution: > > module myalgorithm; > > void test(T)(T t) > { > import std.traits; > mixin("import " ~ std.traits.moduleName!T ~ ";"); > mixin("alias M = " ~ std.traits.moduleName!T ~ ";"); > // The above could be encapsulated into an eponymous template > // that takes T as a parameter and returns the alias > > M.f(t); > } > > What makes them problematic or highly unsavory? I thought #4 in particular > was rather cool, I plan to use it as an example. I also had this idea as workaround, but you can't seriously think this is okay? Importing an entire module at the point I want to call a function is crazy. I don't want to import _everything_ from T's module into my local namespace; that could easily lead to conflicting names in the local scope which would now require disambiguation. This surely represents a far higher probability of name collisions than the theoretical accidental collision that could come from ADL. The ADL style collision isn't accidental though, that's _the whole point_. >> or had any problems with ADL > > https://en.wikipedia.org/wiki/Argument-dependent_name_lookup#Criticism > > Essentially, ADL has awkward problems when getting beyond the simple cases. > It isn't right for D. D requires ADL so much more than C++ does, because the things ADL does in C++ are absolute concrete advertised core value propositions of D. > ADL has the problems I provided a link to. It's never caused me a problem, in like, 15 years or more. This situation in D causes me problems all the time. > In any case, these difficulties are the consequence of trying to write C++ > code in D. You've told me this before, and I find it kind of offensive every time you do, since I've been programming D for like 7 years now, and I definitely don't code D like C++. If anything, I have a strong tendency to code C++ like D, and that has lead to a lot of interesting changes in my C++ style. I'm tired of these sorts of dismissals. You insist that I'm not a 'real' D programmer, or something to that effect. This problem consistently arises when I try to commit to go all in on ranges+UFCS pipeline style programming. There's nothing C++-ey about that. C++ can barely do it. It is the advertised mission of modern D programmers to write code this way, and it's the exact area where the problem I'm trying to express breaks down. The interesting part is, when I do try and code this way in C++ (which is brutal, it's all SFINAE based template constraints and stuff), it actually _works_, simply because ADL works. Pipeline programming is a core value proposition for D, as are uber-powerful templates which leads to making algorithms out of everything. > None of the algorithms used in std.algorithm or elsewhere in > Phobos have this particular issue. Nor have I seen ADL supported in any > other language, despite many supporting generic algorithms. std.algorithm is extremely simple, it doesn't do anything except raw algorithm-ey stuff. It doesn't attempt to invoke functionality on the data it's working on. Right now I'm working on image processing. There are lots of image data types, and they all have things like interpolation and blending functions. Write an image processing algorithm that calls out to lerp or blend, and you'll run into these problems instantly. I was writing some audio software some time back, again, trying to use stream processing extensively because it's a perfect match for that workload, but same problem! Write an algorithm that does _work_, rather than does algorithm logic, and you can't miss this problem. You need to call associated functions to do work. > I do understand trying to write C++ code in D, because my early FORTRAN > programs looked like BASIC, my early C programs looked like FORTRAN, my C++ > code looked like C, etc. Again, stop this. It's insulting, and it really pisses me off. I'm writing textbook modern D, which is code that you can't even express in C++. > What I have provided is a generic way to make ADL work in D, which shows how > adaptable it is. I never said D wasn't adaptable and capable of madhax. I understand very well that D is powerful enough to find a possible work-around for basically anything. You wouldn't believe some of the hacks I'm responsible for! (mostly relating to ref! >_<) It's useful once in a while, but once some particular hax present themselves as rule rather than the excepsion, you find yourself effectively engaged in writing boilerplate. Just like C, but a different kind of boilerplate, and for my money; extremely more complex boilerplate than C/C++, which only experts can read and understand. I am absolutely not okay with that sort of madhax.