Thread overview
Parameter pack expansion
May 30, 2019
Tomas
May 30, 2019
Adam D. Ruppe
May 30, 2019
Tomas
May 30, 2019
ag0aep6g
May 30, 2019
Q. Schroll
May 30, 2019
Tomas
May 30, 2019
I'm very new to D, coming from C++ I'm missing parameter pack expansion and fold expressions.

For example, I want to write a function `f(x[0], ..., x[n])` which accepts any number of objects and calls `g(x[0].member, ..., x[n].member)`.

In C++, I would write this:

   template<class ...X>
   void f(X ... x){
      g(x.member...);
   }

Similar transformation can be also done in C++ on types too:

   template<class ...X>
   using F = G<X::Member...>;

How do I do something like this in D?

Basicaly, how do I preform tuple transformations

X = (X[0], ..., X[n]) ->  TX = (X[0].Member, ... ,X[n].Member)
x = (x[0], ..., x[n]) ->  tx = (x[0].member, ... ,x[0].member)

Here is my best shot in D, it kind of does what I want, but I have do define my own map function `myMap`.

   // Helper function
   auto myMap(alias Fun, X...)(X x) {
     import std.typecons;

     static if (X.length > 1)
       return tuple(Fun(x[0])) ~ myMap!(Fun)(x[1 .. $]);
     else
       return tuple(Fun(x[0]));
   }

   // Do the transformation inside
   void foo(X...)(X x){
      // type transformation
      alias MemberOf(T) = T.Member;
      alias XM = staticMap!(MemberOf, X);

      // value transformation, notice the `expand`!
      auto tx  = myMap!(x => x.member)(x).expand;
   }

What is the recommended what to do this in D? Surely, there has to be a standard function which does exactly(probably better) the same thing as what `myMap` does.
May 30, 2019
On Thursday, 30 May 2019 at 20:20:47 UTC, Tomas wrote:
> How do I do something like this in D?

D's built-in tuples expand automatically when they are used. Library tuples (from phobos std.typecons) have a `.expand` method you can use.

Fun fact: all structs also have a `.tupleof` thing that yields the members. Try this:

struct Foo {int a; string b; }

void test(int, string) {}

Foo foo;
test(foo.tupleof); // works!

> Basicaly, how do I preform tuple transformations

import std.meta;

then staticMap is like what your myMap thing was.

http://dpldocs.info/experimental-docs/std.meta.staticMap.html

May 30, 2019
On 30.05.19 22:20, Tomas wrote:
> Surely, there has to be a standard function which does exactly(probably better) the same thing as what `myMap` does.

Nope.
May 30, 2019
On Thursday, 30 May 2019 at 20:20:47 UTC, Tomas wrote:
> I'm very new to D, coming from C++ I'm missing parameter pack expansion and fold expressions.

I also miss the expansion operator and fold expressions.
In D, there is no such thing, and simulating it in a general way has so much friction, I just used string mixin to solve these.

I even thought about writing a DIP, but I think, it wouldn't make it.
In my static indexing DIP [1], there is a suggestion to add an expansion operator, but that would only work on sequences and similar things.

If it would be implemented, you could place your parameter pack into a Tuple-like structure with an opDispatch that returns such a Tuple again, but the contents would be the member components "projection" to the member. It's doable[2], but the lack of indexing the pack is the main blocker.

If you look closer, the DIP proposes to make "pack..." work by replacing it with pack[0], ..., pack[$ - 1] if the indexing and length are there to do it.

The DIP doesn't give you parameter or type packs, it gives you what you need to implement them; still, fold expressions are still not possible. They are rather easy to implement using D's template mechanisms and/or string mixin mechanisms. The projections to the members in [2] are an example of a fold expression.

[1] https://github.com/dlang/DIPs/pull/155
[2] https://run.dlang.io/is/tIxmQS
May 30, 2019
On Thursday, 30 May 2019 at 20:34:18 UTC, Adam D. Ruppe wrote:
> Foo foo;
> test(foo.tupleof); // works!

This is really neat! I will definitely use this in the future.

> import std.meta;
>
> then staticMap is like what your myMap thing was.
>
> http://dpldocs.info/experimental-docs/std.meta.staticMap.html

I'm already using `staticMap` to transform types but can `staticMap` be used also to transform values? I do not see how.
May 30, 2019
On Thursday, 30 May 2019 at 20:55:00 UTC, Q. Schroll wrote:
> If it would be implemented, you could place your parameter pack into a Tuple-like structure with an opDispatch that returns such a Tuple again, but the contents would be the member components "projection" to the member. It's doable[2], but the lack of indexing the pack is the main blocker.
>
>  ...
>
> [1] https://github.com/dlang/DIPs/pull/155
> [2] https://run.dlang.io/is/tIxmQS

Thanks! Sounds interesting, but right now it is a bit over my head. It will take me some time digest it.