Thread overview
static foreach, expression-Based Contract Syntax and better error messages
Aug 07, 2018
Nicholas Wilson
Aug 07, 2018
Basile B.
Aug 17, 2018
Nicholas Wilson
August 07, 2018
so the following
void foo(As...)(As as)
in
{
   static foreach (a ;as)
   assert(a>0);
}
do
{
}

void main()
{
     foo(1,2,3,4,5);
}

passes and compiles, whereas

void foo(As...)(As as)
static foreach (a ;as)
    in(a>0)
{
}

void main()
{
     foo(1,2,3,4,5);
}

does not compile.  I suppose thats fair enough, there is after all a not very verbose workaround.

I only note this because in researching examples for my multiple template constraints DIP[1], I noticed while I can make individual clauses easier to understand, I realised that recursive templates clauses are still going to be horrible so it would be useful to be able to do

void foo(As...)(As as)
static foreach (alias A ;As)
    if(isFoo!A)
{
    //...
}

and this was the closest thing syntactically. (yes I know I could have use allSatisfy here but for thing like un-recursing
ptrdiff_t countUntil(alias pred = "a == b", R, Rs...)(R haystack, Rs needles)
    if (isForwardRange!R
        && Rs.length > 0
        && isForwardRange!(Rs[0]) == isInputRange!(Rs[0])
        && is(typeof(startsWith!pred(haystack, needles[0])))
        && (Rs.length == 1
            || is(typeof(countUntil!pred(haystack, needles[1 .. $])))))
its not so simple)

Should this work? And is this something people would like to see added to the DIP?

[1]:https://github.com/thewilsonator/DIPs/blob/template-constraints/DIPs/DIP1xxx.md



August 07, 2018
On Tuesday, 7 August 2018 at 07:33:49 UTC, Nicholas Wilson wrote:
> so the following
> void foo(As...)(As as)
> in
> {
>    static foreach (a ;as)
>    assert(a>0);
> }
> do
> {
> }
>
> void main()
> {
>      foo(1,2,3,4,5);
> }
>
> passes and compiles, whereas
>
> void foo(As...)(As as)
> static foreach (a ;as)
>     in(a>0)
> {
> }
>
> void main()
> {
>      foo(1,2,3,4,5);
> }
>
> does not compile.  I suppose thats fair enough, there is after all a not very verbose workaround.
>
> I only note this because in researching examples for my multiple template constraints DIP[1], I noticed while I can make individual clauses easier to understand, I realised that recursive templates clauses are still going to be horrible so it would be useful to be able to do
>
> void foo(As...)(As as)
> static foreach (alias A ;As)
>     if(isFoo!A)
> {
>     //...
> }
> [...]
> Should this work? And is this something people would like to see added to the DIP?

No. At this point syntax of contracts or constraints is getting *really* mad.
I think it's better to put the static loop in the function body, especially since with assert you can format a nice message, while not with constraints.


August 17, 2018
On Tuesday, 7 August 2018 at 08:20:55 UTC, Basile B. wrote:
> On Tuesday, 7 August 2018 at 07:33:49 UTC, Nicholas Wilson wrote:
>> so the following
>> void foo(As...)(As as)
>> in
>> {
>>    static foreach (a ;as)
>>    assert(a>0);
>> }
>> do
>> {
>> }
>>
>> void main()
>> {
>>      foo(1,2,3,4,5);
>> }
>>
>> passes and compiles, whereas
>>
>> void foo(As...)(As as)
>> static foreach (a ;as)
>>     in(a>0)
>> {
>> }
>>
>> void main()
>> {
>>      foo(1,2,3,4,5);
>> }
>>
>> does not compile.  I suppose thats fair enough, there is after all a not very verbose workaround.
>>
>> I only note this because in researching examples for my multiple template constraints DIP[1], I noticed while I can make individual clauses easier to understand, I realised that recursive templates clauses are still going to be horrible so it would be useful to be able to do
>>
>> void foo(As...)(As as)
>> static foreach (alias A ;As)
>>     if(isFoo!A)
>> {
>>     //...
>> }
>> [...]
>> Should this work? And is this something people would like to see added to the DIP?
>
> No. At this point syntax of contracts or constraints is getting *really* mad.
> I think it's better to put the static loop in the function body, especially since with assert you can format a nice message, while not with constraints.

I have decided to make the DIP be consistent with `in` contracts: that is allow both an expression form and block statement form. The block state meant can use static foreach to static assert on variadic lists, while the expression from is more concise.