www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Parameter pack expansion

reply Tomas <skrivantomas seznam.cz> writes:
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
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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
parent Tomas <skrivantomas seznam.cz> writes:
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
prev sibling next sibling parent ag0aep6g <anonymous example.com> writes:
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
prev sibling parent reply Q. Schroll <qs.il.paperinik gmail.com> writes:
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
parent Tomas <skrivantomas seznam.cz> writes:
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.
May 30 2019