Workaround for DIP 1005

Jonathan M Davis via Digitalmars-d digitalmars-d at puremagic.com
Wed Feb 8 21:40:01 PST 2017


On Friday, February 03, 2017 14:43:01 Dominikus Dittes Scherkl via 
Digitalmars-d wrote:
> Any thoughts?

This is really cool, but I have a couple of concerns about this and how it
seems deficient in comparison to DIP 1005. I mentioned it in Andrei's PR for
this, but no one has responded to my comment.

This first problem is UFCS. While this technique works great for parameters
or on types you want to list in the template constraint, I don't see how it
can work with UFCS. So, if you have something like

auto func(alias pred, R)(R range)
    if(isInputRange!R &&
       is(typeof(pred(range.front)) == bool))
{...}

you can do

auto func(alias pred, R)(R range)
    if(from!"std.range.primitives".isInputRange!R &&
       is(typeof(pred(range.front)) == bool))
{...}

but you can't import std.range.primitives.front to make dynamic arrays work,
whereas with DIP 1005, you can just add the import to the function
declaration, and it will work without having to tie the import to a specific
symbol.

And while in many cases, you can just forgo UFCS - e.g.

auto func(P)(P param)
    if(is(typeof(from!"std.algorithm".find(param)) == param))
{...}

that not only doesn't work with the range primitives, but it's bad practice
to use UFCS in the function body and not the template constraint (since the
semantics may not be the same), meaning that not using UFCS in the template
constraint means not using it in the function body for anything that's in
the template constraint (which many folks won't like and others won't
understand, resulting in subtle bugs), and any case where you want a
function to work with types that define a function as a member function as
well as with types that use a free function, you need to use UFCS and thus
cannot choose to not use it in the template constraint.

So, unless there's something that I don't understand about this technique
(which is definitely possible), it seems like it does not work with UFCS and
thus makes it considerably worse than 1005 for a lot of templated code, much
as it would work great for code that doesn't need UFCS.

The other problem is how much more verbose it is. With DIP 1005, you can do

with(import std.datetime)
auto foo(SysTime st1, SysTime st2, Duration d);

The import is only listed once, whereas with this technique, you have to
list it for each symbol. e.g.

auto foo(from!"std.datetime".SysTime st1,
         from!"std.datetime".SysTime st2,
         from!"std.datetime".Duration d);

The result is much more verbose, and if you have several symbols that need
imports between the return type, parameters, and template constraint, you
quickly end up with a lot of extra text in the middle of your function
signatures just because you want to tie the imports to the functions that
use them. With DIP 1005, the imports are next to the function but separate
where they avoid the need for repeating imports and don't get mixed into the
middle of the function signature.

So, while the proposed technique is really cool and clever in what it lets
us do without actually altering the language, it seems like it's quite a bit
worse than DIP 1005. As such, I'm inclined to argue that we should favor DIP
1005 over this proposal, as cool as it is.

- Jonathan M Davis



More information about the Digitalmars-d mailing list