DIP10005: Dependency-Carrying Declarations is now available for community feedback
Chris Wright via Digitalmars-d
digitalmars-d at puremagic.com
Sat Dec 31 08:41:16 PST 2016
On Fri, 30 Dec 2016 20:56:54 -0500, Andrei Alexandrescu wrote:
> On 12/30/16 7:32 PM, Chris Wright wrote:
>> On Fri, 30 Dec 2016 22:42:39 +0000, Stefan Koch wrote:
>>
>>> On Friday, 30 December 2016 at 22:29:18 UTC, Chris Wright wrote:
>>>> * Performance improvements, primarily when a module imports another,
>>>> bulky module for optional functionality.
>>> That is solved by selective imports.
>>
>> Well, not today, but it could be. Same with static imports. Both
>> accomplish this goal better than DIP1005.
>
> Is this fact or opinion? If the former, could you please point where
> DIP1005 is getting it wrong. Thanks.
Consider:
with(import std.range.primitives, std.traits)
{
template Foo(Range) if (isForwardRange!Range && !isArray!Range) {}
template Bar(Range) if (isArray!Range) {}
}
If I invoke Bar, the compiler must read and parse both
std.range.primitives and std.traits.
With static imports:
static import std.range.primitives, std.traits;
template Foo(Range) if (std.range.primitives.isForwardRange!Range
&& !std.traits.isArray!Range) {}
template Bar(Range) if (std.traits.isArray!Range) {}
If I invoke Bar, the compiler must read and parse std.traits but not
std.range.primitives because it is unambiguous that isArray is in
std.traits, not std.range.primivites.
With selective imports likewise.
You're going to respond that I'm only complaining that people can abuse
the syntax. Consider that it also happens if I change the code and forget
to update the imports. Also consider that people are likely to
incorporate several related definitions that tend to use the same imports
in order to save typing. "Be more virtuous" isn't a mantra that actually
leads to better code.
>>>> * Making it easier to locate where things are defined when reading
>>>> code.
>>>
>>> That is solved by selective imports.
>>
>> Static imports do that better than selective imports, though it's more
>> typing.
>
> So whether that's overall better is not settled, is it? We can't really
> define "better" as whatever each participant believes.
Whether the feature is overall better is not settled. Whether locating
where symbols are defined is easier with DIP1005 than with static imports
*is*.
Static imports tell you exactly where the symbol is defined at a glance,
whereas with DIP1005, you have to look through at least two modules.
>> With selective imports, you can either find the declaration in the
>> current module, or find the symbol in an import list. If it's imported,
>> and the module author is using standard code formatting, you will find
>> the import at the top of the module, which will be fast. This is less
>> true with arbitrarily scoped imports.
>>
>> With DIP1005, you rely on there also being selective or static imports.
>> If the module author didn't use them, then you have to pull out grep.
>
> DIP1005 allows the declaration to encapsulate its own dependencies. Of
> course if top-level imports are also present, the benefit erodes.
Consider:
// tons of code
with (import std.traits)
template Bar(Range) if (isArray!Range && !isAbstractClass!Range) {}
// tons more code
I can reasonably guess that the import is required for at least one of
isArray and isAbstractClass, though for all I know, if I'm unfamiliar
with std.traits, the import is unnecessary and both isArray and
isAbstractClass are defined in the current module.
You can fix that with a static or selective import:
with (import std.traits : isArray, isAbstractClass)
template Bar(Range) if (isArray!Range && !isAbstractClass!Range) {}
Far less ambiguous, but your examples all have unmodified with-imports,
and you seem less than keen about selective imports.
>> -- Another thing that just occurred to me: if you're modifying a
>> function signature and that brings in another imported symbol, you
>> don't have to move to the top of the file or struct to add the
>> necessary import. It's a small thing for vim users, who are used to
>> using marks and fast movement commands, but if you're using, say,
>> VSCode, that might be painful.
>
> That's one of the many benefits of encapsulation.
It is a benefit of this DIP. There are many ways to achieve
encapsulation, and there are many effects of encapsulation, and most of
that is irrelevant to this discussion.
FWIW, you could also use current imports immediately before the relevant
declaration. That would be a bad idea in general because it makes it much
harder to locate imports when trying to locate a definition.
More information about the Digitalmars-d
mailing list