www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Tuple poilerplate code

reply JG <someone somewhere.com> writes:
Is there anyway to remove the boilerplate code of dealing with 
tuples:

I find myself having to write things like this fairly often

auto someRandomName  = f(...); //where f returns a tuple with two 
parts
auto firstPart = someRandomName[0];
auto secondPart = someRandomName[1];


Is to possible to write something so that the above is 
essentially equivalent to:

assignTuple!(firstPart,secondPart) = f(...);

The closest I can produce is using a template mixin so that I 
would have to write:

mixin AssignTuple!(()=>f(...),"firstPart","secondPart");
Aug 31 2020
next sibling parent reply user1234 <user1234 12.de> writes:
On Tuesday, 1 September 2020 at 02:08:54 UTC, JG wrote:
 Is there anyway to remove the boilerplate code of dealing with 
 tuples:

 I find myself having to write things like this fairly often

 auto someRandomName  = f(...); //where f returns a tuple with 
 two parts
 auto firstPart = someRandomName[0];
 auto secondPart = someRandomName[1];


 Is to possible to write something so that the above is 
 essentially equivalent to:

 assignTuple!(firstPart,secondPart) = f(...);

 The closest I can produce is using a template mixin so that I 
 would have to write:

 mixin AssignTuple!(()=>f(...),"firstPart","secondPart");
--- void assignTuple(S, T...)(auto ref S s, auto ref T t) { static foreach (i; 0 .. S.length) t[i] = s[i]; } void main() { import std; string a,b; tuple("a", "b").assignTuple(a,b); } ---
Aug 31 2020
parent JG <a b.com> writes:
On Tuesday, 1 September 2020 at 03:51:10 UTC, user1234 wrote:
 On Tuesday, 1 September 2020 at 02:08:54 UTC, JG wrote:
 Is there anyway to remove the boilerplate code of dealing with 
 tuples:

 I find myself having to write things like this fairly often

 auto someRandomName  = f(...); //where f returns a tuple with 
 two parts
 auto firstPart = someRandomName[0];
 auto secondPart = someRandomName[1];


 Is to possible to write something so that the above is 
 essentially equivalent to:

 assignTuple!(firstPart,secondPart) = f(...);

 The closest I can produce is using a template mixin so that I 
 would have to write:

 mixin AssignTuple!(()=>f(...),"firstPart","secondPart");
--- void assignTuple(S, T...)(auto ref S s, auto ref T t) { static foreach (i; 0 .. S.length) t[i] = s[i]; } void main() { import std; string a,b; tuple("a", "b").assignTuple(a,b); } ---
Thanks for your answer. That helps somewhat, however it is still longer and less clear than one would ideally want. In addition you need to use explicit types.
Sep 01 2020
prev sibling next sibling parent Paul Backus <snarwin gmail.com> writes:
On Tuesday, 1 September 2020 at 02:08:54 UTC, JG wrote:
 Is there anyway to remove the boilerplate code of dealing with 
 tuples:

 I find myself having to write things like this fairly often

 auto someRandomName  = f(...); //where f returns a tuple with 
 two parts
 auto firstPart = someRandomName[0];
 auto secondPart = someRandomName[1];
I like using the following snippet for this kind of thing: /// Pass the members of a tuple as arguments to a function template unpack(alias fun) { import std.typecons: isTuple; auto unpack(T)(T args) if (isTuple!T) { return fun(args.expand); } } Usage looks like this: f(...).unpack!((firstPart, secondPart) { // use firstPart and secondPart in here }); It also works very well in range pipelines; for example, auto nums = [1, 2, 3]; auto animals = ["lion", "tiger", "bear"]; zip(nums, animals) .map!(unpack!((num, animal) => animal.repeat(num).joiner(" "))) .each!writeln; ...which prints the output: lion tiger tiger bear bear bear
Sep 01 2020
prev sibling next sibling parent Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Tuesday, 1 September 2020 at 02:08:54 UTC, JG wrote:
 Is there anyway to remove the boilerplate code of dealing with 
 tuples:

 I find myself having to write things like this fairly often

 auto someRandomName  = f(...); //where f returns a tuple with 
 two parts
 auto firstPart = someRandomName[0];
 auto secondPart = someRandomName[1];


 Is to possible to write something so that the above is 
 essentially equivalent to:

 assignTuple!(firstPart,secondPart) = f(...);

 The closest I can produce is using a template mixin so that I 
 would have to write:

 mixin AssignTuple!(()=>f(...),"firstPart","secondPart");
When you know the types, this works: import std.typecons : tuple; import std.meta : AliasSeq; int firstPart; string secondPart; AliasSeq!(firstPart, secondPart) = tuple(1, "foo"); assert(firstPart == 1); assert(secondPart == "foo"); I know Timon Gehr worked on a DIP for improved tuples, which I think would include the syntax `auto (firstPart, secondPart) = tuple(1, "foo");`, but I don't know what's happened to that idea lately. I also feel it's worth pointing out that Paul Backus' code looks elegant when used outside a map as well: tuple(1, "foo").unpack!((i, s) { writeln("i (", typeof(i).stringof, "): ", i, ", s (", typeof(s).stringof, "): ", s); }); Will print: i (int): 1, s (string): foo -- Simen
Sep 01 2020
prev sibling parent reply WebFreak001 <d.forum webfreak.org> writes:
On Tuesday, 1 September 2020 at 02:08:54 UTC, JG wrote:
 [...]
Here is some fun with operator overloading and pointers, but I don't really like it because it seems unsafe: import std; auto _(T...)(return ref T refs) safe { static struct Assigner(Ptrs...) { disable this(this); private Ptrs ptrs; void opAssign(T)(T v) if (T.expand.length == Ptrs.length) { static foreach (i; 0 .. Ptrs.length) *ptrs[i] = v[i]; } } static Assigner!U assigner(U...)(U v) { return Assigner!U(v); } static string assignerCall(size_t len)() { string ret = "assigner("; static foreach (i; 0 .. len) ret ~= "&refs[" ~ i.stringof ~ "], "; return ret ~ ")"; } return mixin(assignerCall!(T.length)); } void main() { string a, b, c; int x; _(a, b, c, x) = tuple("a", "b", "c", 4); writeln(a, b, c, x); _(a, b) = tuple(b, a); writeln(a, b); }
Sep 01 2020
parent reply JG <someone somewhere.com> writes:
Thank you all for the interesting suggestions.
Sep 01 2020
parent JG <someone somewhere.com> writes:
On Wednesday, 2 September 2020 at 03:52:55 UTC, JG wrote:
 Thank you all for the interesting suggestions.
Still thinking about this from time to time. Other than the suggestions given, this is what I have been playing around with. --------------------------------- import std.stdio; import std.typecons : tuple; mixin template assignTuple(alias vars, alias tupleFunc) { import std.conv : to; auto tmp = tupleFunc(); static foreach (i, var ; vars) { mixin("auto " ~ var ~ " = tmp[" ~ i.to!string ~ "];"); } } auto f(int n) { return tuple(n, n+1, n+2, "A string here"); } void main() { mixin assignTuple!(["x","y","z", "str"],()=>f(3)); writeln(x," ",y," ", z," \'",str,"\'"); } --------------------------------- produces --------------------------------- 3 4 5 'A string here' --------------------------------- I have a few questions: 1. Is the above code "bad" for some reason? 2. Is there a way of "hiding" tmp used in the mixin, so that it is not visible in main?
Sep 18 2020