May 10, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday, 24 April 2020 at 21:00:08 UTC, Steven Schveighoffer wrote:
> import std.algorithm : canFind;
> enum anySatisfy(alias F, T...) = [F!(T)...].canFind(true);
> enum allSatisfy(alias F, T...) = ![F!(T)...].canFind(false);
That might be slower than the existing templates (now in core.internal.traits), which don't use template recursion, and short circuit:
template anySatisfy(alias F, Ts...)
{
static foreach (T; Ts)
{
static if (!is(typeof(anySatisfy) == bool) && // not yet defined
F!T)
{
enum anySatisfy = true;
}
}
static if (!is(typeof(anySatisfy) == bool)) // if not yet defined
{
enum anySatisfy = false;
}
}
Your versions also require an extra import (although canFind could be locally copied).
|
May 10, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Treleaven | On Sunday, 10 May 2020 at 08:30:35 UTC, Nick Treleaven wrote:
> On Friday, 24 April 2020 at 21:00:08 UTC, Steven Schveighoffer wrote:
>> import std.algorithm : canFind;
>> enum anySatisfy(alias F, T...) = [F!(T)...].canFind(true);
>> enum allSatisfy(alias F, T...) = ![F!(T)...].canFind(false);
>
> That might be slower than the existing templates (now in core.internal.traits), which don't use template recursion, and short circuit:
>
> template anySatisfy(alias F, Ts...)
> {
> static foreach (T; Ts)
> {
> static if (!is(typeof(anySatisfy) == bool) && // not yet defined
> F!T)
> {
> enum anySatisfy = true;
> }
> }
> static if (!is(typeof(anySatisfy) == bool)) // if not yet defined
> {
> enum anySatisfy = false;
> }
> }
>
> Your versions also require an extra import (although canFind could be locally copied).
Here is how this would look as a type function.
bool anySatisfy(bool function (alias) pred, alias[]... types)
{
foreach(type; types)
{
if (pred(type))
return true;
}
return false;
}
|
May 10, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Treleaven | On 5/10/20 4:30 AM, Nick Treleaven wrote: > On Friday, 24 April 2020 at 21:00:08 UTC, Steven Schveighoffer wrote: >> import std.algorithm : canFind; >> enum anySatisfy(alias F, T...) = [F!(T)...].canFind(true); >> enum allSatisfy(alias F, T...) = ![F!(T)...].canFind(false); > > That might be slower than the existing templates (now in core.internal.traits), which don't use template recursion, and short circuit: > > template anySatisfy(alias F, Ts...) > { > static foreach (T; Ts) > { > static if (!is(typeof(anySatisfy) == bool) && // not yet defined > F!T) > { > enum anySatisfy = true; > } > } > static if (!is(typeof(anySatisfy) == bool)) // if not yet defined > { > enum anySatisfy = false; > } > } I admit, I didn't look at the implementation, I just assumed it was one of the recursive ones. But the "performance" is relative to where the satisfying items are. But it's a good point, evaluating all of the templates to see if one is true leaves some performance on the table, and another reason to prefer a folding mechanism. i.e., this might short circuit automatically (if supported): enum anySatisfy(alias F, T...) = F!(T) || ...; > > Your versions also require an extra import (although canFind could be locally copied). Yeah, a for loop CTFE can easily be created for this if needed. It was just easier to reach for something that exists to show the brevity. -Steve |
May 11, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On Saturday, 9 May 2020 at 00:25:35 UTC, Manu wrote: >> One thing I want to mention: Let Ts be the type sequence int, long, double[]; then >> >> void f(Ts[]...); >> >> becomes ambiguous. > > Does it though? I didn't think it would, but when I tested it just to be sure, it actually compiled to my (and I think everyone else's) great surprise. Let Ts be the type sequence int, long, double[]; then the compiler "rewrites" (for lack of a better word) the declaration void f(Ts[]...); to void f(int __param_0, long __param_1, double[] __param_2...); The dots on __param_0 and __param_1 don't do anything (as far as I know), but make __param_2 a variadic argument. (The compiler copies all the decorations (scope, in, out, ref, and (to my surprise) the dots) to the type sequence for every type.) > I don't think function declarations accept an expression in the argument list... they are declarations. > > Otherwise you'd be able to specify a function like: > void f(10 + 1, Enum.key, nullptr); If Ts contains things that don't resolve to types, the declaration is ill-formed. That's nothing new. > I don't think my DIP interacts with function declarations. It *theoretically* does. I have given you an example. Have a look at it yourself https://run.dlang.io/is/PYKyx1 By the way, you can replace `Ts[]...` by `Ts...` with no difference in the type of `f`. That case is in the darkest corner of D. Just mention it in the DIP so that no one can reject it upon potential breakage that was not addressed. |
May 11, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On Friday, 8 May 2020 at 21:18:26 UTC, Adam D. Ruppe wrote: > On Friday, 8 May 2020 at 20:53:39 UTC, Q. Schroll wrote: >> alias Tup = Tuple!(int, long); > > This is just a struct, the ... shouldn't do anything to it (probably should be a syntax error). It surely is a struct, but it's a struct with an alias-this to a tuple of the kind you're discussing. That's what my question was about. > The ... thing is all about compiler tuples which are unfortunately named the same but totally separate to library tuples. I surely can distinguish a language construct from an aggregate type defined in the library. It's not about the library type! I wasn't fooled by the nomenclature, you were. You all (maybe with exception of Timon Gehr) got me all wrong. My question wasn't about std.typecons.Tuple per se. It was about alias-this. I used std.typecons.Tuple as a well known example of an aggregate type with an alias-this to a tuple (tuple in the sense you're discussing all the time). See the reference now? Consider: struct S(Ts...) { Ts variables; alias variables this; } void f(int, long); auto obj = S!(int, long)(1, 2L); Now, per the DIP, will `f( (obj+5)... )` rewrite to `f(obj.variables[0]+5, obj.variables[1]+5))` by going through S's `alias variables this` or would it just ignore alias this altogether? Is it better formulated, now that I'm not using an example quite many people here are familiar with? |
May 11, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Q. Schroll | On 5/11/20 3:46 PM, Q. Schroll wrote:
> On Friday, 8 May 2020 at 21:18:26 UTC, Adam D. Ruppe wrote:
>> On Friday, 8 May 2020 at 20:53:39 UTC, Q. Schroll wrote:
>>> alias Tup = Tuple!(int, long);
>>
>> This is just a struct, the ... shouldn't do anything to it (probably should be a syntax error).
>
> It surely is a struct, but it's a struct with an alias-this to a tuple of the kind you're discussing. That's what my question was about.
>
>> The ... thing is all about compiler tuples which are unfortunately named the same but totally separate to library tuples.
>
> I surely can distinguish a language construct from an aggregate type defined in the library. It's not about the library type! I wasn't fooled by the nomenclature, you were.
>
> You all (maybe with exception of Timon Gehr) got me all wrong. My question wasn't about std.typecons.Tuple per se. It was about alias-this. I used std.typecons.Tuple as a well known example of an aggregate type with an alias-this to a tuple (tuple in the sense you're discussing all the time). See the reference now?
>
> Consider:
>
> struct S(Ts...)
> {
> Ts variables;
> alias variables this;
> }
>
> void f(int, long);
>
> auto obj = S!(int, long)(1, 2L);
>
> Now, per the DIP, will `f( (obj+5)... )` rewrite to `f(obj.variables[0]+5, obj.variables[1]+5))` by going through S's `alias variables this` or would it just ignore alias this altogether?
>
> Is it better formulated, now that I'm not using an example quite many people here are familiar with?
I think the answer is no.
I think you will have to be explicit in the reference to the variables:
f((obj.variables + 5)...)
This should also work:
f((anyOldStruct.tupleof + 5)...)
and this:
f((someStdTypeconsTuple.expand + 5)...)
There are many expressions that *result* in compiler tuples that would NOT be expanded. e.g. template instantiations and the like. I think only symbols and __traits expressions should be expanded, and not via alias this.
This is something Manu and I discussed on slack, and I think he was going to update the DIP to reflect on how this would work (he may have already, I haven't read it in a while).
-Steve
|
Copyright © 1999-2021 by the D Language Foundation