May 10, 2020
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
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
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
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
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
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
11 12 13 14 15 16 17 18 19 20 21
Next ›   Last »