New blog post on the cost of compile time
Steven Schveighoffer
schveiguy at gmail.com
Sat Feb 18 17:16:18 UTC 2023
On 2/18/23 7:04 AM, Nick Treleaven wrote:
> On Monday, 16 January 2023 at 15:13:04 UTC, Steven Schveighoffer wrote:
>> In general, Phobos templates should try to avoid using simple wrappers
>> for internal things. One thing I didn't discuss in the post is that
>> the `ReturnType` instances here are only ever going to be instantiated
>> *once*, and on something that is *never used* (the lambda function).
>
> If each test used `lvalueOf` from std.traits then the instantiations
> would be reused (there would be 2 just in isInputRange), and likely
> elsewhere too. There could be a convention to use lvalueOf too and avoid
> instantiating rvalueOf for instantiation reuse.
>
> ```d
> is(typeof(() { return (*cast(R*)null).empty; }()) == bool)
> is(typeof(() { return lvalueOf!R.empty; }()) == bool)
> ```
>
> That looks a bit nicer as it says what its intent is. Hopefully it
> wouldn't affect memory/performance much.
>
> Another idea is to factor out all the `r` parameter declarations into
> one, and use that for the return type tests too:
>
> ```d
> // now
> enum isInputRange(R) =
> is(typeof(R.init) == R)
> && is(typeof(() { return (*cast(R*)null).empty; }()) == bool)
> && (is(typeof((return ref R r) => r.front)) ||
> is(typeof(ref (return ref R r) => r.front)))
> && !is(typeof(() { return (*cast(R*)null).front; }()) == void)
> && is(typeof((R r) => r.popFront));
>
> // factored
> enum isInputRange(R) =
> __traits(compiles, (R r) {
> static assert(
> is(typeof(R.init) == R) &&
> is(typeof({ return r.empty; }()) == bool) &&
> is(typeof(() return => r.front)) &&
> is(typeof(ref () return => r.front)) &&
> !is(typeof({ return r.front; }()) == void) &&
> is(typeof({ r.popFront; }))
> );
> });
> ```
> The factored version looks much easier to read for me. I don't know how
> they compare for memory/performance though.
This is how isInputRange used to look. The reason it was changed is
because the compiler now "sees" the different clauses separated by &&,
and will tell you which one failed. When you wrap it like this, it just
sees one big constraint.
I actually did get a PR merged. It wasn't as simple as I had written in
that blog post, due to the stupid `inout` requirement that `inout` data
can only be used inside a function with an `inout` parameter.
I did start with using `lvalueOf!R`, but then realized that since
`isInputRange` validates that `typeof(R.init) == R`, I just used
`R.init` as the parameter.
See the merged PR here: https://github.com/dlang/phobos/pull/8682
-Steve
More information about the Digitalmars-d
mailing list