Should we add `a * b` for vectors?

Walter Bright newshound2 at digitalmars.com
Fri Oct 6 01:01:34 UTC 2017


On 10/5/2017 4:26 AM, Timon Gehr wrote:
>> I know that some of the UFCS code was written without regard to hijacking.
>> ...
> 
> I think it is by design. Lookup first tries to find members of the type, and 
> only if they don't exist applies UFCS lookup. Therefore, if members are added to 
> the type or made visible, this may hijack existing UFCS usages.

It may have been done that way to avoid breaking existing code.

> The way to fix it is to do UFCS lookup always and then error out if both UFCS 
> and member lookup match, but there is probably quite some code relying on the 
> fact that you can provide a custom implementation of a general UFCS function by 
> just adding a member. Also, with the hijacking error if you actually meant the 
> member function the only way out I see is to use __traits(getMember, ...) for 
> disambiguation.
> 
> (BTW: Local imports allow hijacking too. Maybe this one could be fixed?)

I thought that was taken care of when the whole import lookup mechanism was 
redone a year or two ago.


>>> The intention of the code was to demonstrate that a type can pass 
>>> isInputRange in the same module in which it does not support front. This is 
>>> an example of surprising name lookup behavior.
>>
>> I submit it is surprising only if you're used to ADL :-)
>> ...
> 
> I'm not used to ADL. I think it is surprising because input ranges support 
> front. ;) (It's not surprising to _me_, I'm rather familiar with D's features, 
> especially those added before last year or so. My statement is more that it 
> could be surprising to many, and that it is not necessarily reasonable to blame 
> them for being surprised.)

When I learn a new language, I am sometimes surprised at the depth of my 
preconceived notions about how they work that turns out to be very specific to a 
language I am very used to.


>> D's name lookup rules were quite simple, and deliberately set up that way. 
>> Unfortunately, most people thought they were unintuitive. It turns out that 
>> simple algorithms are not intuitive, and we now have a fairly complex lookup 
>> system. Martin and I implemented it, and probably neither of us completely 
>> understands it. I find it regrettable that things have gotten to that state.
>> ...
> 
> It might make sense to sit down at some point and see what goals the complex 
> rules try to achieve and then come up with simpler rules that achieve the same 
> (or better) goals.

There wasn't a lack of discussion about the import lookup rules :-)


> One thing that currently works is having the following string constant in a 
> util.d file:
> 
> enum ufcs_=q{
>      private{
>          import std.typecons: Proxy;
>          struct UFCS(T){ T payload; mixin Proxy!payload; }
>          auto ufcs(T)(T arg)@trusted{ return *cast(UFCS!T*)&arg; }
>      }
> };
> 
> Then, the following code compiles and runs:
> 
> import util: ufcs_;
> mixin(ufcs_);
> 
> struct Iota{ private int a,b; }
> auto iota(int a,int b){ return Iota(a,b); }
> 
> @property int front(Iota i){ return i.a; }
> @property bool empty(Iota i){ return i.a>=i.b; }
> void popFront(ref Iota i){ ++i.a; }
> 
> void main(){
>      import std.algorithm, std.stdio;
>      iota(0,10).ufcs.each!writeln; // ok
> }
> 
> This exploits what seems to be a serious encapsulation-breaking bug in 
> std.typecons.Proxy in order to pick up all UFCS functions visible from the 
> current module, but a safe version of this could be made.

Nice

>> Doing this kind of wrapper doesn't work for operator overloading, which brings 
>> us back to ADL is for operator overloading.
> 
> Why does it not work for operator overloading?

3+s


More information about the Digitalmars-d mailing list