Thread overview
tuple(...).each error; why does foreach work and std.algorithms.each doesn't ?
Feb 11, 2020
wjoe
Feb 11, 2020
Adam D. Ruppe
Feb 11, 2020
wjoe
Feb 11, 2020
Paul Backus
Feb 11, 2020
wjoe
Feb 11, 2020
Adam D. Ruppe
Feb 11, 2020
wjoe
February 11, 2020
Consider a function to format the parameters of a function call:

pure nothrow string fmtArgs(ARGS...)(ARGS args)
{
   string result;

   // 1)
   foreach(a; args) {
      result ~= a.to!string;
   }

   // 2)
   args.each!(a => result ~= a.to!string);

   return result;
}

In my mind, if something works with foreach, it should also work with std.algorithm.each.
However if I try something like 2) the compiler complains with error: cannot deduce function from argument types !()(uint, int)...

Technically I'd like to transform args into a range/array of strings but I'm not smart enough to understand the error messages these functions in std.algorithms produce.

How is 1) different from 2) ?

February 11, 2020
On Tuesday, 11 February 2020 at 18:11:44 UTC, wjoe wrote:
> In my mind, if something works with foreach, it should also work with std.algorithm.each.

They are very different, the each thing only works for ranges whereas foreach works with a variety of things.

> How is 1) different from 2) ?

The ARGS... is a compiler list and can have multiple different types included. Moreover, it will auto-expand when you use it to call a function etc.

You can sometimes do [args] - with the [] around it to turn into an array. Then you can .each it and so on. But they must already be of compatible types to do that since an array elements must all be the same thing.

I would suggest just using foreach for this.
February 11, 2020
On Tuesday, 11 February 2020 at 18:21:11 UTC, Adam D. Ruppe wrote:
> On Tuesday, 11 February 2020 at 18:11:44 UTC, wjoe wrote:
>> In my mind, if something works with foreach, it should also work with std.algorithm.each.
>
> They are very different, the each thing only works for ranges whereas foreach works with a variety of things.
>
>> How is 1) different from 2) ?
>
> The ARGS... is a compiler list and can have multiple different types included. Moreover, it will auto-expand when you use it to call a function etc.
>
> You can sometimes do [args] - with the [] around it to turn into an array. Then you can .each it and so on. But they must already be of compatible types to do that since an array elements must all be the same thing.
>
> I would suggest just using foreach for this.

What's a compiler list... is that something like a tuple? or more like a macro expansion?
Or is it only valid to use in a foreach to take advantage of each item individually and for expansion in a function call ?
Is it possible to partially expand like:

void fn(int, uint) {}
and ARGS(string, int, uint)
and call fn(args[1..$]);

Is that possible?

as for the format function...foreach works as expected so I'll just keep that. Thanks for your fast reply :)
February 11, 2020
On Tuesday, 11 February 2020 at 18:55:45 UTC, wjoe wrote:
> What's a compiler list... is that something like a tuple? or more like a macro expansion?
> Or is it only valid to use in a foreach to take advantage of each item individually and for expansion in a function call ?
> Is it possible to partially expand like:
>
> void fn(int, uint) {}
> and ARGS(string, int, uint)
> and call fn(args[1..$]);
>
> Is that possible?

This article answers all of your questions:

https://dlang.org/articles/ctarguments.html
February 11, 2020
On Tuesday, 11 February 2020 at 18:55:45 UTC, wjoe wrote:
> What's a compiler list... is that something like a tuple?

Yea, they are frequently called tuples too. It is basically just a list of arguments used for a function call that the compiler treats somewat magically.

> Is it possible to partially expand like:
>
> void fn(int, uint) {}
> and ARGS(string, int, uint)
> and call fn(args[1..$]);

Yes, slicing is the exact syntax for it. You can slice and index as if it were an array.
February 11, 2020
On Tuesday, 11 February 2020 at 19:05:19 UTC, Adam D. Ruppe wrote:
> On Tuesday, 11 February 2020 at 18:55:45 UTC, wjoe wrote:
>> What's a compiler list... is that something like a tuple?
>
> Yea, they are frequently called tuples too. It is basically just a list of arguments used for a function call that the compiler treats somewat magically.
>
>> Is it possible to partially expand like:
>>
>> void fn(int, uint) {}
>> and ARGS(string, int, uint)
>> and call fn(args[1..$]);
>
> Yes, slicing is the exact syntax for it. You can slice and index as if it were an array.

Cool. thanks for your reply :)
February 11, 2020
On Tuesday, 11 February 2020 at 19:04:17 UTC, Paul Backus wrote:
> On Tuesday, 11 February 2020 at 18:55:45 UTC, wjoe wrote:
>> What's a compiler list... is that something like a tuple? or more like a macro expansion?
>> Or is it only valid to use in a foreach to take advantage of each item individually and for expansion in a function call ?
>> Is it possible to partially expand like:
>>
>> void fn(int, uint) {}
>> and ARGS(string, int, uint)
>> and call fn(args[1..$]);
>>
>> Is that possible?
>
> This article answers all of your questions:
>
> https://dlang.org/articles/ctarguments.html

That's more information than I had hoped for. Thank you :)