phobos dependencies
Joseph Rushton Wakeling
joseph.wakeling at webdrake.net
Fri Dec 20 05:45:07 PST 2013
On 20/12/13 10:06, Meta wrote:
> 2 comes with its own problems, though. With imports at the top, you can easily
> tell what the module imports at a glance. Putting imports into the deepest
> possible scopes where they are used will make it a huge chore to hunt all the
> imports down. You can of course grep for "import" (or ctrl+f for more plebeian
> editors), but you still don't have that singular list in one place that you can
> easily look at to tell what the module imports.
Conversely, one problem of imports at the top is that it's easy for unnecessary
imports to hang around just because you don't have a direct association between
the import and what it's actually used for.
I think the real issue we face is that it's not possible to really gain the
advantages of deeply-nested-as-possible imports without _also_ breaking up the
modules; we can't have Andrei's strategy (2) without some of strategy (3).
Example: std.algorithm.topN, the only part of std.algorithm (apart from
unittests) that requires std.random:
void topN(alias less = "a < b",
SwapStrategy ss = SwapStrategy.unstable,
Range)(Range r, size_t nth)
if (isRandomAccessRange!(Range) && hasLength!Range)
{
static assert(ss == SwapStrategy.unstable,
"Stable topN not yet implemented");
while (r.length > nth)
{
auto pivot = uniform(0, r.length);
// ... etc. ...
}
}
Now, at first glance it's easy to just insert an extra line before "auto pivot =
...":
import std.random : uniform;
... but it quickly becomes non-trivial if you want to do what really ought to be
an option here, and allow a non-default RNG to be passed to the function:
void topN(alias less = "a < b",
SwapStrategy ss = SwapStrategy.unstable,
Range, RandomGen)(Range r, size_t nth, ref RandomGen rng)
if (isRandomAccessRange!(Range) && hasLength!Range
&& isUniformRNG!RandomGen) // <--- needs std.random.isUniformRNG
{
static assert(ss == SwapStrategy.unstable,
"Stable topN not yet implemented");
while (r.length > nth)
{
auto pivot = uniform(0, r.length, rng);
// ... etc. ...
}
}
// New function to support old 2-parameter version using default RNG
void topN(alias less = "a < b",
SwapStrategy ss = SwapStrategy.unstable,
Range)(Range r, size_t nth)
if (isRandomAccessRange!(Range) && hasLength!Range)
{
topN(r, ss, rndGen); <---- needs std.random.rndGen;
}
The second of the two needed imports is easy and can be nested inside the
function, but the first -- the isUniformRNG template -- requires the import in
the module's own scope.
So, to really allow std.algorithm to do away with its dependency on std.random,
you need to break isUniformRNG and similar templates away from the rest of the
std.random functionality.
(Yes, I know, you could break topN out from the rest of std.random, but remember
that topN itself is only dependent on std.random for the case where you're using
the unstable swap strategy.)
I'd hypothesize that probably it would be productive to start modularizing
Phobos modules by separating out all the various helper templates like
isUniformRNG, after which it should be much easier to avoid needing top-level
module imports.
More information about the Digitalmars-d
mailing list