www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - ref tuples

reply "Brad Anderson" <eco gnuk.net> writes:
C++11's std::tuple includes a function std::tie that takes 
references to the arguments and returns a tuple that maintains 
the references to the arguments.

Along with the usual cases where you'd want reference semantics 
it also enables this interesting construct for unpacking tuples.

int a, b;
tie(a, b) = make_tuple(1, 2);

assert(a == 1 && b == 2);

Is there any way to do something similar with std.typecons.Tuple?
Jul 02 2013
next sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 07/03/13 02:22, Brad Anderson wrote:
 C++11's std::tuple includes a function std::tie that takes references to the
arguments and returns a tuple that maintains the references to the arguments.
 
 Along with the usual cases where you'd want reference semantics it also
enables this interesting construct for unpacking tuples.
 
 int a, b;
 tie(a, b) = make_tuple(1, 2);
 
 assert(a == 1 && b == 2);
 
 Is there any way to do something similar with std.typecons.Tuple?
Well, aliases can be used to get a similar effect. template tie(A...) { alias tie = A; } tie!(a, b) = tuple(1, 2); artur
Jul 03 2013
next sibling parent "Dicebot" <public dicebot.lv> writes:
On Wednesday, 3 July 2013 at 11:54:39 UTC, Artur Skawina wrote:
 Well, aliases can be used to get a similar effect.

    template tie(A...) { alias tie = A; }
    tie!(a, b) = tuple(1, 2);

 artur
Which is actually already in Phobos: TypeTuple!(a, b) = tuple(1, 2);
Jul 03 2013
prev sibling parent reply "Brad Anderson" <eco gnuk.net> writes:
On Wednesday, 3 July 2013 at 11:54:39 UTC, Artur Skawina wrote:
 On 07/03/13 02:22, Brad Anderson wrote:
 C++11's std::tuple includes a function std::tie that takes 
 references to the arguments and returns a tuple that maintains 
 the references to the arguments.
 
 Along with the usual cases where you'd want reference 
 semantics it also enables this interesting construct for 
 unpacking tuples.
 
 int a, b;
 tie(a, b) = make_tuple(1, 2);
 
 assert(a == 1 && b == 2);
 
 Is there any way to do something similar with 
 std.typecons.Tuple?
Well, aliases can be used to get a similar effect. template tie(A...) { alias tie = A; } tie!(a, b) = tuple(1, 2); artur
That won't work. a and b aren't held as references (also you passed them as type parameters :P).
Jul 03 2013
parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 07/03/13 18:29, Brad Anderson wrote:
 On Wednesday, 3 July 2013 at 11:54:39 UTC, Artur Skawina wrote:
 On 07/03/13 02:22, Brad Anderson wrote:
 C++11's std::tuple includes a function std::tie that takes references to the
arguments and returns a tuple that maintains the references to the arguments.

 Along with the usual cases where you'd want reference semantics it also
enables this interesting construct for unpacking tuples.

 int a, b;
 tie(a, b) = make_tuple(1, 2);

 assert(a == 1 && b == 2);

 Is there any way to do something similar with std.typecons.Tuple?
Well, aliases can be used to get a similar effect. template tie(A...) { alias tie = A; } tie!(a, b) = tuple(1, 2);
That won't work. a and b aren't held as references (also you passed them as type parameters :P).
Try it... And, yes, the fact that 'A...' template parms accept symbols is not exactly obvious. But it's much more useful that way. artur
Jul 03 2013
parent reply "Brad Anderson" <eco gnuk.net> writes:
On Wednesday, 3 July 2013 at 16:35:18 UTC, Artur Skawina wrote:
 On 07/03/13 18:29, Brad Anderson wrote:
 On Wednesday, 3 July 2013 at 11:54:39 UTC, Artur Skawina wrote:
 On 07/03/13 02:22, Brad Anderson wrote:
 C++11's std::tuple includes a function std::tie that takes 
 references to the arguments and returns a tuple that 
 maintains the references to the arguments.

 Along with the usual cases where you'd want reference 
 semantics it also enables this interesting construct for 
 unpacking tuples.

 int a, b;
 tie(a, b) = make_tuple(1, 2);

 assert(a == 1 && b == 2);

 Is there any way to do something similar with 
 std.typecons.Tuple?
Well, aliases can be used to get a similar effect. template tie(A...) { alias tie = A; } tie!(a, b) = tuple(1, 2);
That won't work. a and b aren't held as references (also you passed them as type parameters :P).
Try it... And, yes, the fact that 'A...' template parms accept symbols is not exactly obvious. But it's much more useful that way. artur
Huh, I had no idea you could do something like that. I stand corrected. Thanks. That does get tie = working but doesn't work if you want to pass it around which is actually more at the heart of what I'm interested in. To get straight to the point, I was playing around with implementing bearophile's enumerate() feature request (something I've wanted myself). Both his posted solution [1] and my own quick testing hack (auto enumerate(Range)(Range r) { return zip(sequence!"n"(), r); }) lose the ability to do ref elements in foreach that can modify the source range: --- auto a = ["a", "b", "c"]; foreach(i, ref item; a.enumerate()) item = to!string(i); assert(a == ["0", "1", "2"]); // fails, a is still ["a", "b", "c"] --- They don't work because both the tuples he returns from front and the tuples zip creates aren't references to the originals so you are just changing the copy stored in the tuple. Something like "alias RefIntTuple = Tuple!(ref int, ref int);" gives a compiler error (Error: expression expected, not 'ref'). 1. http://d.puremagic.com/issues/show_bug.cgi?id=5550#c2
Jul 03 2013
parent Artur Skawina <art.08.09 gmail.com> writes:
On 07/03/13 19:10, Brad Anderson wrote:
 On Wednesday, 3 July 2013 at 16:35:18 UTC, Artur Skawina wrote:
 On 07/03/13 18:29, Brad Anderson wrote:
 On Wednesday, 3 July 2013 at 11:54:39 UTC, Artur Skawina wrote:
 On 07/03/13 02:22, Brad Anderson wrote:
 C++11's std::tuple includes a function std::tie that takes references to the
arguments and returns a tuple that maintains the references to the arguments.

 Along with the usual cases where you'd want reference semantics it also
enables this interesting construct for unpacking tuples.

 int a, b;
 tie(a, b) = make_tuple(1, 2);

 assert(a == 1 && b == 2);

 Is there any way to do something similar with std.typecons.Tuple?
Well, aliases can be used to get a similar effect. template tie(A...) { alias tie = A; } tie!(a, b) = tuple(1, 2);
That won't work. a and b aren't held as references (also you passed them as type parameters :P).
Try it... And, yes, the fact that 'A...' template parms accept symbols is not exactly obvious. But it's much more useful that way. artur
Huh, I had no idea you could do something like that. I stand corrected. Thanks. That does get tie = working but doesn't work if you want to pass it around which is actually more at the heart of what I'm interested in. To get straight to the point, I was playing around with implementing bearophile's enumerate() feature request (something I've wanted myself). Both his posted solution [1] and my own quick testing hack (auto enumerate(Range)(Range r) { return zip(sequence!"n"(), r); }) lose the ability to do ref elements in foreach that can modify the source range: --- auto a = ["a", "b", "c"]; foreach(i, ref item; a.enumerate()) item = to!string(i); assert(a == ["0", "1", "2"]); // fails, a is still ["a", "b", "c"] --- They don't work because both the tuples he returns from front and the tuples zip creates aren't references to the originals so you are just changing the copy stored in the tuple. Something like "alias RefIntTuple = Tuple!(ref int, ref int);" gives a compiler error (Error: expression expected, not 'ref'). 1. http://d.puremagic.com/issues/show_bug.cgi?id=5550#c2
D does not yet have proper ref types, which means a lot of things are not possible, at least not directly. And a lot of hacks are required to achieve certain effects. Anyway, the following seems to work - it's bearophiles code from the mentioned bugzilla entry with some tweaks. It's dirty enough, so I shouldn't be posting this on a 'learn' ML... It's meant more as an illustration of the language deficiencies. Please do not use anything like this. :) import std.stdio, std.algorithm, std.range, std.typecons, std.traits, std.array; struct RefHack(T) { T* ptr; ref get() property { return *ptr; } alias get this; } auto refHack(T)(ref T a) { return RefHack!T(&a); } struct Enumerate(R) { R r; int i; property bool empty() { return r.empty; } property Tuple!(typeof(this.i), typeof(refHack(r.front))) front() { return typeof(return)(i, refHack(r.front)); } void popFront() { this.r.popFront(); this.i++; } } Enumerate!R enumerate(R)(R range, int start=0) if (isInputRange!R) { return Enumerate!R(range, start); } void main() { auto flags = [0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1]; flags.enumerate(2).filter!q{!a[1]}().map!q{a[0]}().writeln(); { import std.conv; auto a = ["a", "b", "c"]; foreach(i, ref item; a.enumerate()) item = to!string(i); assert(a == ["0", "1", "2"]); } } artur
Jul 03 2013
prev sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On 2013-07-03, 02:22, Brad Anderson wrote:

 C++11's std::tuple includes a function std::tie that takes references to  
 the arguments and returns a tuple that maintains the references to the  
 arguments.

 Along with the usual cases where you'd want reference semantics it also  
 enables this interesting construct for unpacking tuples.

 int a, b;
 tie(a, b) = make_tuple(1, 2);

 assert(a == 1 && b == 2);

 Is there any way to do something similar with std.typecons.Tuple?
Not that I know of. But, Philippe Sigaud's dranges[1] library includes a RefTuple[2], which should do what you want. [1]: https://github.com/dawgfoto/dranges/ [2]: https://github.com/dawgfoto/dranges/blob/master/reftuple.d -- Simen
Jul 03 2013