Re: tuples from text file
On 12/19/17 7:47 PM, codephantom wrote: so I have a text file containing 3 lines(e.g): 5, "hello", 4.3 "hello", 4.3 "hello", "world", 1, 2, 3, 5.5 Now I want to create tuples from each line. However, (using line 1 as example), I get: Tuple!string("5, \"hello\", 4.3") but I really want: Tuple!(int, string, double)(5, "hello", 4.3) I know why - because a line is a string. But anyone got an idea on how to extract the string into separate elements that can be correctly 'tuple'd" according to the type of each element? Well, you need to know at compile time the types you are expecting. Then you just parse them out. You can't decide tuples at runtime. -Steve
Re: Tuples not working?
On 01/09/2015 10:42 AM, Jonathan Marler wrote: import std.stdio; import std.typecons; void main() { alias TL = Tuple!(int, long, float); foreach (i, T; TL) writefln(TL[%d] = %s, i, typeid(T)); } Why is this not working? D:\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(419): Error: need 'this' for '_expand_field_0' of type 'int' D:\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(419): Error: need 'this' for '_expand_field_1' of type 'long' D:\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(419): Error: need 'this' for '_expand_field_2' of type 'float' Tried to compile using dmd 2.066 and dmd 2.067. Code taken directly from dlang website here (http://dlang.org/tuple.html). Thanks. Broken documentation presumable because the feature changed later on. The code works if you we std.typetuple.TypeTuple: import std.stdio; import std.typetuple; void main() { alias TL = TypeTuple!(int, long, float); foreach (i, T; TL) writefln(TL[%d] = %s, i, typeid(T)); } Ali
Re: Tuples printing
[(1, 2, 3), (4, 5, 6), (7, 8, 9)] Good idea. And shoud easy to be used by foreach. Frank
Re: Tuples printing
On Thu, Jul 03, 2014 at 09:52:35AM +, bearophile via Digitalmars-d wrote: [...] void main() { import std.stdio, std.typecons; alias RGB = Tuple!(ubyte,R, ubyte,G, ubyte,B); const arr = [RGB(1, 2, 3), RGB(4, 5, 6), RGB(7, 8, 9)]; writeln(arr); } It prints: [const(Tuple!(ubyte, R, ubyte, G, ubyte, B))(1, 2, 3), const(Tuple!(ubyte, R, ubyte, G, ubyte, B))(4, 5, 6), const(Tuple!(ubyte, R, ubyte, G, ubyte, B))(7, 8, 9)] If your range of tuples grows larger, the printing becomes too much long and too much noisy. The signal gets almost lots. A simple solution is to print tuples inside ranges as just (field1, field2, ...), and keep the same printing style if you print a single tuple: writeln(RGB(1, 2, 3)) writeln(arr); == Tuple!(ubyte, R, ubyte, G, ubyte, B))(1, 2, 3) [(1, 2, 3), (4, 5, 6), (7, 8, 9)] [...] I like this idea. Looking at the code, it seems that Tuple.toString was specifically written to output tuples in the current format, though admittedly it's rather verbose. We *could* probably overload/rewrite it so that it permits %(...%) format specifiers, upon which the user could specify a different format, like the ones you suggested. (This could constitute a legitimate (rather than toy) use case for custom format specifiers, that I've written about. :-P) T -- MACINTOSH: Most Applications Crash, If Not, The Operating System Hangs
Re: Tuples and compile-time assigned properties
On 19/09/13 17:21, Dicebot wrote: +1 Why do you need to use tuples and manually force them into struct behavior instead of simply using structs? I guess I was thinking it'd be more finnicky to do something like struct EdgeProperties { double weight; } struct VertexProperties { size_t colour; string name; } auto g = Graph!(EdgeProperties, VertexProperties); ... than to allow the user the flexibility of just knocking up a Tuple in the moment. But now that I think about it, it's not actually more complicated really.
Re: Tuples and compile-time assigned properties
On Thursday, 19 September 2013 at 14:56:08 UTC, Artur Skawina wrote: I'm not sure i understand your problem, but you could use structs. ie: struct VertexProperties { size_t color; string name; } You can get the field names and types at CT and work with that. +1 Why do you need to use tuples and manually force them into struct behavior instead of simply using structs?
Re: Tuples and compile-time assigned properties
On 09/19/13 16:40, Joseph Rushton Wakeling wrote: alias EdgeProperties = Tuple!(double, weight); alias VertexProperties = Tuple!(size_t, colour, string, name); So then, you'd be able to extract the list of variable names and types at compile time and use them to create the underlying data structures required; and similarly you'd be able to create a set of public interfaces that gives you access to those members. With that in mind, there are a number of potential issues that arise: (i) is there a compile-time constraint via which I can insist that every member of the tuple must be named? (ii) is there an easy way to extract all the names of tuple members as an array of strings? Can anyone advise? I'm not sure i understand your problem, but you could use structs. ie: struct VertexProperties { size_t color; string name; } You can get the field names and types at CT and work with that. artur
Re: Tuples and compile-time assigned properties
On 19/09/13 16:55, Artur Skawina wrote: I'm not sure i understand your problem, but you could use structs. ie: struct VertexProperties { size_t color; string name; } You can get the field names and types at CT and work with that. Yes, that's a good suggestion. I guess I was thinking that it'd be easier to do something like auto g = Graph!(Tuple!(double, weight), Tuple!(size_t, colour, string, name)); ... than to force the user to define a struct up front and pass it as template parameter.
Re: Tuples and compile-time assigned properties
On 09/19/13 17:22, Joseph Rushton Wakeling wrote: On 19/09/13 16:55, Artur Skawina wrote: I'm not sure i understand your problem, but you could use structs. ie: struct VertexProperties { size_t color; string name; } You can get the field names and types at CT and work with that. Yes, that's a good suggestion. I guess I was thinking that it'd be easier to do something like auto g = Graph!(Tuple!(double, weight), Tuple!(size_t, colour, string, name)); ... than to force the user to define a struct up front and pass it as template parameter. Yeah, support for anonymous structs as template parms would be useful; auto g = Graph!(struct { double weight; size_t color; string name }); But that's not currently possible. You can do something like: auto g = Graph!q{ double weight; size_t color; string name; }; then, inside the Graph template: // template Graph(string F, ...) { struct S { mixin (F); } // ...look at fields of 'S'... (This will work if you only need builtin types and/or custom ones already available in the Graph template) artur
Re: Tuples
On Monday, 27 May 2013 at 03:28:07 UTC, deadalnix wrote: On Monday, 27 May 2013 at 02:31:50 UTC, Jonathan M Davis wrote: On Monday, May 27, 2013 04:24:51 Diggory wrote: It also shouldn't break any code since the only addition to TypeTuple is a check to make sure that the undocumented behaviour of using it with non-types is disallowed, and in the case that this undocumented feature is used the code can simply switch to StaticTuple and be done. Well, changing TypeTuple to only accept types _will_ break code. It gets used quite heavily with foreach to get a static foreach, and that can involve using expressions instead of types. Anyone using TypeTuple heavily knows what it can do and will probably have used it for expressions at some point. It wouldn't surprise me in the least if it's already done in Phobos, and there's no way to know how much it is or isn't done elsewhere. Granted that nobody understand them, it is fair to say it should be changed. In case people agree: https://github.com/D-Programming-Language/phobos/pull/1309
Re: Tuples
On Monday, 27 May 2013 at 09:25:14 UTC, Diggory wrote: Granted that nobody understand them, it is fair to say it should be changed. In case people agree: https://github.com/D-Programming-Language/phobos/pull/1309 I'm all for it. Thank you.
Re: Tuples
On Sunday, 26 May 2013 at 15:48:00 UTC, Russel Winder wrote: I wonder if people coming to D, looking for information about tuples, will get confused by http://dlang.org/tuple.html which seems to tell people they have to roll their own, and http://dlang.org/phobos/std_typecons.html which tells people they have been pre-rolled in the standard library? I found this especially confusing because the built-in Tuple is defined differently. The Tuple in that example is equivalent to the definition of TypeTuple, and yet TypeTuple is supposedly specific to types while that example (as so by implication TypeTuple) apparently works just as well with other contents. On top of that Tuple is the one that only works with types - any string expressions are extracted and used as names... Surely a tuple which can only store types should be a TypeTyple and a tuple which can store anything should be a Tuple.
Re: Tuples
On Sunday, May 26, 2013 22:38:24 Diggory wrote: On Sunday, 26 May 2013 at 15:48:00 UTC, Russel Winder wrote: I wonder if people coming to D, looking for information about tuples, will get confused by http://dlang.org/tuple.html which seems to tell people they have to roll their own, and http://dlang.org/phobos/std_typecons.html which tells people they have been pre-rolled in the standard library? I found this especially confusing because the built-in Tuple is defined differently. The Tuple in that example is equivalent to the definition of TypeTuple, and yet TypeTuple is supposedly specific to types while that example (as so by implication TypeTuple) apparently works just as well with other contents. On top of that Tuple is the one that only works with types - any string expressions are extracted and used as names... Surely a tuple which can only store types should be a TypeTyple and a tuple which can store anything should be a Tuple. I really wish that the term tuple didn't get used with the built-in tuples / TypeTuples. They _aren't_ tuples. They're similar, but they don't nest, and they cause a lot of confusion with std.typecons.Tuple. And they're only compile-time constructs to boot. - Jonathan M Davis
Re: Tuples
I have certainly been confused by the term 'tuple' used in D countless times. It seems to exist in a variety of different contexts, and every time I think I understood it, I realise I'm probably wrong some time later. There seems to be poor/no documentation comparing/distinguishing various D tuples, also, there seems to be no real explicit syntax, which makes it hard to recognise. I can kinda handle a Tuple template, and then there are these type tuples, and then expression tuples? What is the relationship between these? Are they compatible? How do I distinguish them? Someone that understand what they're talking about should take some time to write a comprehensive article on the matter :) Some of the things I have read seem to presume that I already know what it's talking about, and as a result, lead to dismissing or misunderstanding the article. I think the practical take-away from my experience is that it ends up as one of those 'too hard' concepts, that I develop a tendency to actively avoid dealing with because it's confused me a number of times. I typically just start typing stuff and hope it works. And if it doesn't I fiddle with it until it eventually does (or I give up), and I never *really* understand why. I'll bet I'm not the only one... On 27 May 2013 10:25, Jonathan M Davis jmdavisp...@gmx.com wrote: On Sunday, May 26, 2013 22:38:24 Diggory wrote: On Sunday, 26 May 2013 at 15:48:00 UTC, Russel Winder wrote: I wonder if people coming to D, looking for information about tuples, will get confused by http://dlang.org/tuple.html which seems to tell people they have to roll their own, and http://dlang.org/phobos/std_typecons.html which tells people they have been pre-rolled in the standard library? I found this especially confusing because the built-in Tuple is defined differently. The Tuple in that example is equivalent to the definition of TypeTuple, and yet TypeTuple is supposedly specific to types while that example (as so by implication TypeTuple) apparently works just as well with other contents. On top of that Tuple is the one that only works with types - any string expressions are extracted and used as names... Surely a tuple which can only store types should be a TypeTyple and a tuple which can store anything should be a Tuple. I really wish that the term tuple didn't get used with the built-in tuples / TypeTuples. They _aren't_ tuples. They're similar, but they don't nest, and they cause a lot of confusion with std.typecons.Tuple. And they're only compile-time constructs to boot. - Jonathan M Davis
Re: Tuples
On Monday, May 27, 2013 11:21:08 Manu wrote: I have certainly been confused by the term 'tuple' used in D countless times. It seems to exist in a variety of different contexts, and every time I think I understood it, I realise I'm probably wrong some time later. There seems to be poor/no documentation comparing/distinguishing various D tuples, also, there seems to be no real explicit syntax, which makes it hard to recognise. I can kinda handle a Tuple template, and then there are these type tuples, and then expression tuples? What is the relationship between these? Are they compatible? How do I distinguish them? You basically just have to worry about Tuple and TypeTuple. Tuple is of course very easy to understand. TypeTuple is then just an alias for the built-in tuples, which can hold basically anything. They're what template parameter lists, function parameter lists, template argument lists, and function argument lists are made of. And you can use them handily in other places (such as foreach) by using TypeTuple explicitly. I believe that an expression tuple is simply a TypeTuple which holds only expressions. In practice, I think that the differences are fairly simple, but they take quite a bit to wrap your head around - primarily due to the terminology used rather than the actual concept. Someone that understand what they're talking about should take some time to write a comprehensive article on the matter :) I guess that I'll have to look at doing that after I finish the article that I'm writing on ranges (that I really need to finish...). Some of the things I have read seem to presume that I already know what it's talking about, and as a result, lead to dismissing or misunderstanding the article. I generally know what's going on with D, but there were talks at dconf that taught be stuff about D that I'd either forgotten or never known (like some of what was going on with moves in Ali's talk). D is nowhere near as bad C++ with regards to how complicated it is, but it's still quite complicated. I think the practical take-away from my experience is that it ends up as one of those 'too hard' concepts, that I develop a tendency to actively avoid dealing with because it's confused me a number of times. I typically just start typing stuff and hope it works. And if it doesn't I fiddle with it until it eventually does (or I give up), and I never *really* understand why. I'll bet I'm not the only one... It's well worth understanding TypeTuple well enough to use it with foreach, as it's a great way to generate unit tests, particularly when you're dealing with templated functions. Phobos does that quite a lot, particularly with strings. Take splitLines unit test for example foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) { auto s = to!S(\rpeter\n\rpaul\r\njerry\u2028ice\u2029cream\n\nsunday\n); auto lines = splitLines(s); assert(lines.length == 9); assert(lines[0] == ); assert(lines[1] == peter); assert(lines[2] == ); assert(lines[3] == paul); assert(lines[4] == jerry); assert(lines[5] == ice); assert(lines[6] == cream); assert(lines[7] == ); assert(lines[8] == sunday); lines = splitLines(s, KeepTerminator.yes); assert(lines.length == 9); assert(lines[0] == \r); assert(lines[1] == peter\n); assert(lines[2] == \r); assert(lines[3] == paul\r\n); assert(lines[4] == jerry\u2028); assert(lines[5] == ice\u2029); assert(lines[6] == cream\n); assert(lines[7] == \n); assert(lines[8] == sunday\n); s.popBack(); // Lop-off trailing \n lines = splitLines(s); assert(lines.length == 9); assert(lines[8] == sunday); lines = splitLines(s, KeepTerminator.yes); assert(lines.length == 9); assert(lines[8] == sunday); } You get to unit test with 6 different types while only writing the code once. That can be _extremely_ useful. - Jonathan M Davis
Re: Tuples
On Monday, 27 May 2013 at 01:36:58 UTC, Jonathan M Davis wrote: On Monday, May 27, 2013 11:21:08 Manu wrote: I have certainly been confused by the term 'tuple' used in D countless times. It seems to exist in a variety of different contexts, and every time I think I understood it, I realise I'm probably wrong some time later. There seems to be poor/no documentation comparing/distinguishing various D tuples, also, there seems to be no real explicit syntax, which makes it hard to recognise. I can kinda handle a Tuple template, and then there are these type tuples, and then expression tuples? What is the relationship between these? Are they compatible? How do I distinguish them? You basically just have to worry about Tuple and TypeTuple. Tuple is of course very easy to understand. TypeTuple is then just an alias for the built-in tuples, which can hold basically anything. They're what template parameter lists, function parameter lists, template argument lists, and function argument lists are made of. And you can use them handily in other places (such as foreach) by using TypeTuple explicitly. I believe that an expression tuple is simply a TypeTuple which holds only expressions. In practice, I think that the differences are fairly simple, but they take quite a bit to wrap your head around - primarily due to the terminology used rather than the actual concept. Someone that understand what they're talking about should take some time to write a comprehensive article on the matter :) I guess that I'll have to look at doing that after I finish the article that I'm writing on ranges (that I really need to finish...). Some of the things I have read seem to presume that I already know what it's talking about, and as a result, lead to dismissing or misunderstanding the article. I generally know what's going on with D, but there were talks at dconf that taught be stuff about D that I'd either forgotten or never known (like some of what was going on with moves in Ali's talk). D is nowhere near as bad C++ with regards to how complicated it is, but it's still quite complicated. I think the practical take-away from my experience is that it ends up as one of those 'too hard' concepts, that I develop a tendency to actively avoid dealing with because it's confused me a number of times. I typically just start typing stuff and hope it works. And if it doesn't I fiddle with it until it eventually does (or I give up), and I never *really* understand why. I'll bet I'm not the only one... It's well worth understanding TypeTuple well enough to use it with foreach, as it's a great way to generate unit tests, particularly when you're dealing with templated functions. Phobos does that quite a lot, particularly with strings. Take splitLines unit test for example foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) { auto s = to!S(\rpeter\n\rpaul\r\njerry\u2028ice\u2029cream\n\nsunday\n); auto lines = splitLines(s); assert(lines.length == 9); assert(lines[0] == ); assert(lines[1] == peter); assert(lines[2] == ); assert(lines[3] == paul); assert(lines[4] == jerry); assert(lines[5] == ice); assert(lines[6] == cream); assert(lines[7] == ); assert(lines[8] == sunday); lines = splitLines(s, KeepTerminator.yes); assert(lines.length == 9); assert(lines[0] == \r); assert(lines[1] == peter\n); assert(lines[2] == \r); assert(lines[3] == paul\r\n); assert(lines[4] == jerry\u2028); assert(lines[5] == ice\u2029); assert(lines[6] == cream\n); assert(lines[7] == \n); assert(lines[8] == sunday\n); s.popBack(); // Lop-off trailing \n lines = splitLines(s); assert(lines.length == 9); assert(lines[8] == sunday); lines = splitLines(s, KeepTerminator.yes); assert(lines.length == 9); assert(lines[8] == sunday); } You get to unit test with 6 different types while only writing the code once. That can be _extremely_ useful. - Jonathan M Davis IMO we should have the following: Tuple - Current Tuple implementation, equivalent to C++ tuple with the extra naming feature. Can be instantiated and passed around. StaticTuple - Current TypeTuple implementation, equivalent to type of ... parameter in template arguments. Should not be instantiable. TypeTuple - A StaticTyple where all parts have been statically checked to be types. It should be easy to instantiate an actual Tuple using a TypeTuple. Note that the template system allows them to be the same type, ie. a StaticTuple!(int, float) == TypeTuple!(int, float) while a TypeTuple!(Hello) will fail to compile. ExpressionTuple - A StaticTuple where all parts have been statically checked to be expressions. It would be much easier to understand and it fills a big gap in
Re: Tuples
On Monday, May 27, 2013 04:24:51 Diggory wrote: It also shouldn't break any code since the only addition to TypeTuple is a check to make sure that the undocumented behaviour of using it with non-types is disallowed, and in the case that this undocumented feature is used the code can simply switch to StaticTuple and be done. Well, changing TypeTuple to only accept types _will_ break code. It gets used quite heavily with foreach to get a static foreach, and that can involve using expressions instead of types. Anyone using TypeTuple heavily knows what it can do and will probably have used it for expressions at some point. It wouldn't surprise me in the least if it's already done in Phobos, and there's no way to know how much it is or isn't done elsewhere. Because you're generally in control of the TypeTuples that you're using (you aren't usually getting the from APIs and the like), I really don' think that the fact that it can hold both types and expressions is a big deal. I expect that it pretty much never causes problems in actual code. It just makes it so that the name sucks. I don't think that we'd gain much (if anything) by separating out TypeTuple into three different types. Renaming it would be nice, but given the current push to stop making breaking changes like that, I would expect that at best, we'd get an alias with a better name. - Jonathan M Davis
Re: Tuples
On Monday, 27 May 2013 at 02:31:50 UTC, Jonathan M Davis wrote: On Monday, May 27, 2013 04:24:51 Diggory wrote: It also shouldn't break any code since the only addition to TypeTuple is a check to make sure that the undocumented behaviour of using it with non-types is disallowed, and in the case that this undocumented feature is used the code can simply switch to StaticTuple and be done. Well, changing TypeTuple to only accept types _will_ break code. It gets used quite heavily with foreach to get a static foreach, and that can involve using expressions instead of types. Anyone using TypeTuple heavily knows what it can do and will probably have used it for expressions at some point. It wouldn't surprise me in the least if it's already done in Phobos, and there's no way to know how much it is or isn't done elsewhere. Because you're generally in control of the TypeTuples that you're using (you aren't usually getting the from APIs and the like), I really don' think that the fact that it can hold both types and expressions is a big deal. I expect that it pretty much never causes problems in actual code. It just makes it so that the name sucks. I don't think that we'd gain much (if anything) by separating out TypeTuple into three different types. Renaming it would be nice, but given the current push to stop making breaking changes like that, I would expect that at best, we'd get an alias with a better name. - Jonathan M Davis Hmm, given that the fix can be entirely automated incredibly simply with find and replace it doesn't seem that bad, especially as the broken behaviour is undocumented. Given that the documentation specifically disambiguates between TypeTuples and ExpressionTuples I think at least emitting a warning when non-types are used to a TypeTuple is reasonable.
Re: Tuples
On Monday, 27 May 2013 at 02:31:50 UTC, Jonathan M Davis wrote: On Monday, May 27, 2013 04:24:51 Diggory wrote: It also shouldn't break any code since the only addition to TypeTuple is a check to make sure that the undocumented behaviour of using it with non-types is disallowed, and in the case that this undocumented feature is used the code can simply switch to StaticTuple and be done. Well, changing TypeTuple to only accept types _will_ break code. It gets used quite heavily with foreach to get a static foreach, and that can involve using expressions instead of types. Anyone using TypeTuple heavily knows what it can do and will probably have used it for expressions at some point. It wouldn't surprise me in the least if it's already done in Phobos, and there's no way to know how much it is or isn't done elsewhere. Granted that nobody understand them, it is fair to say it should be changed.
Re: Tuples and variable-length template parameter lists
On 11/05/2012 06:14 PM, Simen Kjaeraas wrote: std.typecons.Tuple does a bit of magic behind the scenes. This includes ridding itself of non-type parameters. Simply put, you can imagine inserting the type tuple directly into the function definition: void add(ID id, size_t arg0, real arg1, value arg2); as you probably notice, the last argument looks weird. Now, Phobos does not currently have a staticFilter template, nor does it have an isType template, so here are implementations of those: add would then have this signature: void add(ID id, staticFilter!(isType, Properties)); Oh, very cool! Thanks ever so much for that. Incidentally, and I don't understand why, using isTypeTuple also seems to work ... Is there a case for some patches adding those features to Phobos?
Re: Tuples and variable-length template parameter lists
On 2012-11-05, 15:53, Joseph Rushton Wakeling wrote: Hello all, Suppose I want to define a tuple type which may have a variable length, e.g.: template Tup(ID, Properties...) { static if(Properties.length == 0) alias Tuple!(ID, id) Tup; else alias Tuple!(ID, id, Properties) Tup; } Now, it's trivial to include an arbitrary selection of named values in this, e.g. auto t1 = Tup!(size_t, real, value)(3, 4.5); writeln(t1); writeln(t1.id, , t1.value); auto t2 = Tup!(size_t, real, value, bool, active)(3, 4.5, true); writeln(t2); writeln(t2.id, , t2.value, , t2.active); However, suppose now I want to define a container struct which holds an array of tuples of the specified type. Here's what I came up with: struct Container(ID, Properties...) { Tup!(ID, Properties)[] contents; void add(ID i, Properties p) { static if(Properties.length == 0) contents ~= Tup!(ID)(i); else contents ~= Tup!(ID, Properties)(i, p); } } Now, if I make properties empty, this works just fine: auto c1 = Container!(size_t)(); c1.add(3); c1.add(7); c1.add(2); writeln(c1); foreach(t, tup; c1.contents) writeln([, t, ] , tup.id); writeln(); ... and likewise if I pass the container a list of value types without value names: auto c2 = Container!(size_t, real, real)(); c2.add(5, 3.2, 5.6); writeln(c2); writeln(); ... but if I try asking the container to store a tuple with _named_ values, e.g. auto c3 = Container!(size_t, real, value)(); then compilation fails with the following error message: tupcontainer.d(7): Error: tuple Properties is used as a type tupcontainer.d(12): Error: template std.typecons.Tuple!(ulong,id,real,value).Tuple.__ctor does not match any function template declaration /usr/local/include/d2/std/typecons.d(406): Error: template std.typecons.Tuple!(ulong,id,real,value).Tuple.__ctor cannot deduce template function from argument types !()(ulong,_error_) tupcontainer.d(51): Error: template instance tupcontainer.Container!(ulong,real,value) error instantiating I'm confused as to why the Container struct cannot take these template parameters when the corresponding parameters work just fine for Tup. Can anyone advise what the problem is and if it's possible to get the Container working as envisioned? std.typecons.Tuple does a bit of magic behind the scenes. This includes ridding itself of non-type parameters. Simply put, you can imagine inserting the type tuple directly into the function definition: void add(ID id, size_t arg0, real arg1, value arg2); as you probably notice, the last argument looks weird. Now, Phobos does not currently have a staticFilter template, nor does it have an isType template, so here are implementations of those: template staticFilter( alias pred, T... ) { static if ( T.length == 0 ) { alias TypeTuple!( ) staticFilter; } else static if ( pred!( T[0] ) ) { alias TypeTuple!( T[0], staticFilter!( pred, T[1..$] ) ) staticFilter; } else { alias staticFilter!( pred, T[1..$] ) staticFilter; } } unittest { static struct S(T...){} assert( is( S!(staticFilter!(isType, int, float)) == S!(int, float) ) ); assert( is( S!(staticFilter!(isType, int, foo, float)) == S!(int, float) ) ); assert( is( S!(staticFilter!(isType, foo, bar)) == S!() ) ); } template isType( T... ) if ( T.length == 1 ) { enum isType = !is( typeof( T[0] ) ); } unittest { struct S {} class C {} assert( isType!int ); assert( isType!string ); assert( isType!S ); assert( isType!C ); assert( !isType!1 ); assert( !isType! ); assert( !isType!(S( )) ); } add would then have this signature: void add(ID id, staticFilter!(isType, Properties)); -- Simen
Re: Tuples citizenship
On Friday, March 02, 2012 11:41:16 Dmitry Olshansky wrote: On 02.03.2012 6:06, bearophile wrote: Jonathan M Davis: Yes, but chaining functions is the issue. It doesn't work well with tuples unless the function you're passing the result to wants the tuple. If all it wants is one piece of the tuple, then that doesn't work well at all. just stick in .expand ? void f(int x, int y){ } void main() { Tuple!(int, int) a; f(a.expand); } That's assuming that you're passing all of the pieces of the tuple to the function. Often, that's not the case at all. Take the findSplit trio, for instance. What are the odds that you're going to want to pass all of the elements in the tuples that any of the return to another function? About zero, I'd say. It's _much_ more likely that you're going to want to take the results and then pass _one_ of them to another function. So, as it stands, chaining with those functions just doesn't work unless you only care about one of the results in the tuple. - Jonathan M Davis
Re: Tuples citizenship
Le 02/03/2012 00:09, Jonathan M Davis a écrit : When you're looking to mutate existing variables in the caller, using out parameters results in cleaner code. I'd argue that not mutating parameter result in cleaner code most of the time. Tuples are inherently messier, because you have to deal with multiple return values. They also often do poorly when you need to use the functional programming, because often you want all of the return values for later use but only want to pass _one_ of them to the function that you're passing the result to. The first time I encountered tuple was using Caml. This claim doesn't support my practical experience.
Re: Tuples citizenship
Jonathan M Davis jmdavisp...@gmx.com wrote: That's assuming that you're passing all of the pieces of the tuple to the function. Often, that's not the case at all. Take the findSplit trio, for instance. What are the odds that you're going to want to pass all of the elements in the tuples that any of the return to another function? About zero, I'd say. It's _much_ more likely that you're going to want to take the results and then pass _one_ of them to another function. So, as it stands, chaining with those functions just doesn't work unless you only care about one of the results in the tuple. - Jonathan M Davis How does 'out' make chaining any easier? Suppose we have a `R3 findSplit2(R1, R2, out R4, out R5)`, how to chain if we want to pass the R4 to another function? R5 ignored; R4 theRange; findSplit2(haystack, needle, theRange, ignored); return doSomething(theRange); vs return doSomething(findSplit(haystack, needle)[1]);
Re: Tuples citizenship
Le 02/03/2012 03:06, bearophile a écrit : Jonathan M Davis: Yes, but chaining functions is the issue. It doesn't work well with tuples unless the function you're passing the result to wants the tuple. If all it wants is one piece of the tuple, then that doesn't work well at all. You're forced to assign the tuple to something else and then call then function rather than chain calls. In the years I have used a mountain of tuples in Python, but I barely perceive that problem, so I think it's not so bad. int exp; auto result = frexp(value, exp); vs auto tup = frexp(value); result = tup[0]; exp = tup[1]; I have assumed to use a sane tuple unpacking syntax. So the second part of your comparison is: immutable (result, exp) = frexp(value); You got it right. +1
Re: Tuples citizenship
Le 02/03/2012 02:10, Jonathan M Davis a écrit : On Thursday, March 01, 2012 18:57:15 bearophile wrote: Jonathan M Davis: They also often do poorly when you need to use the functional programming, As you know functional languages use tuples all the time. Yes, but chaining functions is the issue. It doesn't work well with tuples unless the function you're passing the result to wants the tuple. If all it wants is one piece of the tuple, then that doesn't work well at all. You're forced to assign the tuple to something else and then call then function rather than chain calls. That's one of the reasons that you constantly end up using stuff like let expressions and pattern matching in functional languages. You don't _want_ a tuple. Dealing with a tuple is annoying. It's just that it's often the best tool that you have to pass disparate stuff around, so that's what you use. And if you're not looking to assign the parts of a tuple to existing variables, then they're not quite as bad as when you are, since you don't necessarily have to then assign the pieces to other variables. There are parts of your post that I don't fully understand. It is often really annoying to have to deal with tuple return values, because you have to worry about unpacking the result. I don't want to use a tuple in the caller. Tuples are generally for grouping unrelated data that you don't necessarily want to keep togother (since if you did, you'd generally use a struct). I want the result to actually be assigned to variables. That is definitely cleaner with out than with tuples. int exp; auto result = frexp(value, exp); vs auto tup = frexp(value); result = tup[0]; exp = tup[1]; Getting tuple return values is annoying. Yes, it can be useful, but most stuff doesn't operate on tuples. It operates on the pieces of tuples. So, you have to constantly break them up. So, using out results in much nicer code. It always feels like I'm fighting the code when I have to deal with tuple return values. - Jonathan M Davis Do you rally think that shorter is always better ? I don't think so. I think better is what the piece of code do pretty much what you expect it to do. And most of the time, I want to pass argument to a function not return value throw arguments. At the callee place, version look just like any other function call, but exp isn't a parameter, it is actually a returned value. You cannot know that reading the code, you need to know about frexp declaration - thus you scroll more source code/documentation or rely on your memory that will sometime fail. To emphasis that, just imagine the same scenario with a function that isn't from the standard lib. This practice will confuse a newcomer that don't know the stdlib well, and, used in thrid party code, will confuse anyone expect the one that write that piece of code.
Re: Tuples citizenship
On Friday, March 02, 2012 09:31:14 kennytm wrote: Jonathan M Davis jmdavisp...@gmx.com wrote: That's assuming that you're passing all of the pieces of the tuple to the function. Often, that's not the case at all. Take the findSplit trio, for instance. What are the odds that you're going to want to pass all of the elements in the tuples that any of the return to another function? About zero, I'd say. It's _much_ more likely that you're going to want to take the results and then pass _one_ of them to another function. So, as it stands, chaining with those functions just doesn't work unless you only care about one of the results in the tuple. - Jonathan M Davis How does 'out' make chaining any easier? Suppose we have a `R3 findSplit2(R1, R2, out R4, out R5)`, how to chain if we want to pass the R4 to another function? R5 ignored; R4 theRange; findSplit2(haystack, needle, theRange, ignored); return doSomething(theRange); vs return doSomething(findSplit(haystack, needle)[1]); True, you can't chain using the out parameters, but you _can_ chain using the return value, whereas if you have a tuple, you can't chain _at all_ unless you actually need all of the returned values (either as a tuple or expanded) or if you only need _one_ of the returned values, in which case you can use the subscript operator. So, you can definitely chain better without a tuple than with. - Jonathan M Davis
Re: Tuples citizenship
On Friday, March 02, 2012 10:27:02 deadalnix wrote: Le 02/03/2012 00:09, Jonathan M Davis a écrit : When you're looking to mutate existing variables in the caller, using out parameters results in cleaner code. I'd argue that not mutating parameter result in cleaner code most of the time. Tuples are inherently messier, because you have to deal with multiple return values. They also often do poorly when you need to use the functional programming, because often you want all of the return values for later use but only want to pass _one_ of them to the function that you're passing the result to. The first time I encountered tuple was using Caml. This claim doesn't support my practical experience. Yes. Functional languages use tuples. But I'm talking about chaining functions like you would in a functional language. But functional languages use pattern matching and other stuff to make it not as big a problem as it is in D, and often in functional languages, you _still_ have to do their equivalent of assigning the pieces of the tuple to variables. Tuples are a bane of function chaining. - Jonathan M Davis
Re: Tuples citizenship
Jonathan M Davis jmdavisp...@gmx.com wrote: On Friday, March 02, 2012 09:31:14 kennytm wrote: Jonathan M Davis jmdavisp...@gmx.com wrote: That's assuming that you're passing all of the pieces of the tuple to the function. Often, that's not the case at all. Take the findSplit trio, for instance. What are the odds that you're going to want to pass all of the elements in the tuples that any of the return to another function? About zero, I'd say. It's _much_ more likely that you're going to want to take the results and then pass _one_ of them to another function. So, as it stands, chaining with those functions just doesn't work unless you only care about one of the results in the tuple. - Jonathan M Davis How does 'out' make chaining any easier? Suppose we have a `R3 findSplit2(R1, R2, out R4, out R5)`, how to chain if we want to pass the R4 to another function? R5 ignored; R4 theRange; findSplit2(haystack, needle, theRange, ignored); return doSomething(theRange); vs return doSomething(findSplit(haystack, needle)[1]); True, you can't chain using the out parameters, but you _can_ chain using the return value, whereas if you have a tuple, you can't chain _at all_ unless you actually need all of the returned values (either as a tuple or expanded) or if you only need _one_ of the returned values, in which case you can use the subscript operator. So, you can definitely chain better without a tuple than with. - Jonathan M Davis You can just chain with return doSomething(findSplit(haystack, needle)[0]); if you just need the return value. Compare with 'out': R4 ignored; R5 ignored2; return doSomething(findSplit(haystack, needle, ignored, ignored2)); How do you chain with _partial_ amount of return values with 'out'?
Re: Tuples citizenship
On 01.03.2012 23:08, bearophile wrote: I think std.typecons.Tuples merit to be a little more citizens in D and Phobos. I think reducing the usage of out argument, and replacing them with a tuple result, will avoid mistakes and make the code look better. In std.math there are functions that maybe are better to use std.typecons.Tuple: pure nothrow @trusted real frexp(real value, out int exp); == pure nothrow @trusted Tuple!(real, int) frexp(real value); nothrow @trusted real remquo(real x, real y, out int n); == nothrow @trusted Tuple!(real, int) remquo(real x, real y); They're defined that way because they come from C, and they're in IEEE754.
Re: Tuples citizenship
On Friday, March 02, 2012 09:53:19 kennytm wrote: You can just chain with return doSomething(findSplit(haystack, needle)[0]); if you just need the return value. Compare with 'out': R4 ignored; R5 ignored2; return doSomething(findSplit(haystack, needle, ignored, ignored2)); How do you chain with _partial_ amount of return values with 'out'? If the function uses out, then you can chain the return value without losing the values which were assigned to the out arguments, but if you have a tuple, and you select one of the elements in the tuple to chain, you lose the others. The only way to get _all_ of the values in the tuple is to assign the tuple to a variable, in which case, you can't chain at all. - Jonathan M Davis
Re: Tuples citizenship
Le 02/03/2012 11:10, Jonathan M Davis a écrit : On Friday, March 02, 2012 09:53:19 kennytm wrote: You can just chain with return doSomething(findSplit(haystack, needle)[0]); if you just need the return value. Compare with 'out': R4 ignored; R5 ignored2; return doSomething(findSplit(haystack, needle, ignored, ignored2)); How do you chain with _partial_ amount of return values with 'out'? If the function uses out, then you can chain the return value without losing the values which were assigned to the out arguments, but if you have a tuple, and you select one of the elements in the tuple to chain, you lose the others. The only way to get _all_ of the values in the tuple is to assign the tuple to a variable, in which case, you can't chain at all. - Jonathan M Davis But you are assigning to a variable, you just declare it before. Additionally, you loose all possibility to use auto.
Re: Tuples citizenship
Jonathan M Davis jmdavisp...@gmx.com wrote: On Friday, March 02, 2012 09:53:19 kennytm wrote: You can just chain with return doSomething(findSplit(haystack, needle)[0]); if you just need the return value. Compare with 'out': R4 ignored; R5 ignored2; return doSomething(findSplit(haystack, needle, ignored, ignored2)); How do you chain with _partial_ amount of return values with 'out'? If the function uses out, then you can chain the return value without losing the values which were assigned to the out arguments, but if you have a tuple, and you select one of the elements in the tuple to chain, you lose the others. The only way to get _all_ of the values in the tuple is to assign the tuple to a variable, in which case, you can't chain at all. - Jonathan M Davis I see what you mean. However, this is useful only when you know one of the return value is special, and make the rest 'out' parameters, e.g. File openFile(string fn, string mode, out ErrorCode errCode); because the API designer know people seldom focus on the 'errCode'. But if not all return values are considered unimportant (such as findSplit and remquo), randomly making some of them as the 'out' parameter just make the normal use cases more messy. Besides, you can't use type inference with 'out' parameters. You don't actually know the types R4 and R5 in my findSplit2 example.
Re: Tuples citizenship
On Friday, 2 March 2012 at 10:13:17 UTC, Jonathan M Davis wrote: If the function uses out, then you can chain the return value without losing the values which were assigned to the out arguments, but if you have a tuple, and you select one of the elements in the tuple to chain, you lose the others. The only way to get _all_ of the values in the tuple is to assign the tuple to a variable, in which case, you can't chain at all. - Jonathan M Davis Sure, but due to D's syntax which doesn't distinguish in/out/ref params in a function call, this is quite confusing to read: when you read f(x,y) which is in, which is out? If D's syntax was f(x,@y) (@ to distinguish out or ref parameter), this would be easy to read, but this isn't the case. At least with tuples you don't have this issue. Not that I consider tuples always the good answer: for the common use case where you want to return an error code and a result, the Maybe monad is better.. BR, renoX
Re: Tuples citizenship
On Friday, March 02, 2012 12:59:43 kennytm wrote: Jonathan M Davis jmdavisp...@gmx.com wrote: On Friday, March 02, 2012 09:53:19 kennytm wrote: You can just chain with return doSomething(findSplit(haystack, needle)[0]); if you just need the return value. Compare with 'out': R4 ignored; R5 ignored2; return doSomething(findSplit(haystack, needle, ignored, ignored2)); How do you chain with _partial_ amount of return values with 'out'? If the function uses out, then you can chain the return value without losing the values which were assigned to the out arguments, but if you have a tuple, and you select one of the elements in the tuple to chain, you lose the others. The only way to get _all_ of the values in the tuple is to assign the tuple to a variable, in which case, you can't chain at all. - Jonathan M Davis I see what you mean. However, this is useful only when you know one of the return value is special, and make the rest 'out' parameters, e.g. File openFile(string fn, string mode, out ErrorCode errCode); because the API designer know people seldom focus on the 'errCode'. But if not all return values are considered unimportant (such as findSplit and remquo), randomly making some of them as the 'out' parameter just make the normal use cases more messy. Besides, you can't use type inference with 'out' parameters. You don't actually know the types R4 and R5 in my findSplit2 example. It's not like using out is fantastic and tuple sucks. They both have pros and cons. My point is that it's not the case that always returning tuples is better, which seems to be the point that Bearophile is trying to push. There _are_ downsides to returning tuples. Whether a tuple or an out parameter is better depends on the function and the context in which it is used. - Jonathan M Davis
Re: Tuples citizenship
Jonathan M Davis jmdavisp...@gmx.com wrote: It's not like using out is fantastic and tuple sucks. They both have pros and cons. My point is that it's not the case that always returning tuples is better, which seems to be the point that Bearophile is trying to push. There _are_ downsides to returning tuples. Whether a tuple or an out parameter is better depends on the function and the context in which it is used. - Jonathan M Davis bearophile's example (frexp, remquo) are good examples where tuple return is better than 'out' parameters though. Another Phobos function, I think, which should use 'out' instead of Tuples is: - std.file.getTimes (have the two 'out' parameters, and the function itself returns 'void'!) While some functions should remain using 'out': - std.stream.InputStream.read (due to overloading) And of course the extern(C) functions need to use 'out' instead of Tuple return :)
Re: Tuples citizenship
Has anyone seen my recent thread about using the if+auto feature and opCast(bool)? It's not related to tuples but I thought it was a cool D feature. I admit I named the thread a pretty stupid name, but it was 6 AM when I posted it :) (http://forum.dlang.org/thread/mailman.195.1330399006.24984.digitalmar...@puremagic.com)
Re: Tuples citizenship
On Thursday, March 01, 2012 17:08:44 bearophile wrote: I think std.typecons.Tuples merit to be a little more citizens in D and Phobos. I think reducing the usage of out argument, and replacing them with a tuple result, will avoid mistakes and make the code look better. In std.math there are functions that maybe are better to use std.typecons.Tuple: pure nothrow @trusted real frexp(real value, out int exp); == pure nothrow @trusted Tuple!(real, int) frexp(real value); [snip] Having good tuple support is great, but out parameters are great too. I'm sure that there are plenty of cases where using out parameters is actually far cleaner than using tuples, since you don't have multiple return values to deal with. So, better enabling tuples is great, but I don't think that we're necessarily moving in a good direction if we're trying to eliminate out parameters in favor of tuples. - Jonathan M Davis
Re: Tuples citizenship
bearophile bearophileh...@lycos.com wrote: (snip) It's good for tuples to become more common in D code. Some time ago I have asked the built-in associative arrays to grow a method to iterate on key-value pairs, named byPair: http://d.puremagic.com/issues/show_bug.cgi?id=5466 (snip) Bye, bearophile Associative arrays (should) have UFCS, so one could just define @property auto byPair(AA)(AA aa) { return zip(aa.byKey, aa.byValue); } in std.array. Or object.di could just define a Pair!(K,V) structure which a Tuple!(K,V) has an opAssign defined for it.
Re: Tuples citizenship
Le 01/03/2012 23:33, Jonathan M Davis a écrit : On Thursday, March 01, 2012 17:08:44 bearophile wrote: I think std.typecons.Tuples merit to be a little more citizens in D and Phobos. I think reducing the usage of out argument, and replacing them with a tuple result, will avoid mistakes and make the code look better. In std.math there are functions that maybe are better to use std.typecons.Tuple: pure nothrow @trusted real frexp(real value, out int exp); == pure nothrow @trusted Tuple!(real, int) frexp(real value); [snip] Having good tuple support is great, but out parameters are great too. I'm sure that there are plenty of cases where using out parameters is actually far cleaner than using tuples, since you don't have multiple return values to deal with. So, better enabling tuples is great, but I don't think that we're necessarily moving in a good direction if we're trying to eliminate out parameters in favor of tuples. - Jonathan M Davis I don't think out parameter is a great idea. This is rather confusing. I tend to think as function's parameter as input of the function and return value as an output. Books usualy agree, so I guess it is a valid point. OOP give us another parameter to play with : this. It act as a state that can be modified. UFCS is nice to extends that outside OOP. This is a way better alternative than out parameter. Tuples are nice too. Since we have auto, this isn't a big deal. Both should be preferred to out parameters IMO, because the later cannot be differentiated at the calling point and force the programer to refers to the function declaration all the time or use its - limited and sometime inaccurate - memory. This is something we want to avoid.
Re: Tuples citizenship
On Friday, March 02, 2012 00:05:22 deadalnix wrote: Le 01/03/2012 23:33, Jonathan M Davis a écrit : On Thursday, March 01, 2012 17:08:44 bearophile wrote: I think std.typecons.Tuples merit to be a little more citizens in D and Phobos. I think reducing the usage of out argument, and replacing them with a tuple result, will avoid mistakes and make the code look better. In std.math there are functions that maybe are better to use std.typecons.Tuple: pure nothrow @trusted real frexp(real value, out int exp); == pure nothrow @trusted Tuple!(real, int) frexp(real value); [snip] Having good tuple support is great, but out parameters are great too. I'm sure that there are plenty of cases where using out parameters is actually far cleaner than using tuples, since you don't have multiple return values to deal with. So, better enabling tuples is great, but I don't think that we're necessarily moving in a good direction if we're trying to eliminate out parameters in favor of tuples. - Jonathan M Davis I don't think out parameter is a great idea. This is rather confusing. I tend to think as function's parameter as input of the function and return value as an output. Books usualy agree, so I guess it is a valid point. OOP give us another parameter to play with : this. It act as a state that can be modified. UFCS is nice to extends that outside OOP. This is a way better alternative than out parameter. Tuples are nice too. Since we have auto, this isn't a big deal. Both should be preferred to out parameters IMO, because the later cannot be differentiated at the calling point and force the programer to refers to the function declaration all the time or use its - limited and sometime inaccurate - memory. This is something we want to avoid. When you're looking to mutate existing variables in the caller, using out parameters results in cleaner code. Tuples are inherently messier, because you have to deal with multiple return values. They also often do poorly when you need to use the functional programming, because often you want all of the return values for later use but only want to pass _one_ of them to the function that you're passing the result to. At other times, tuples are nicer - like when you actually _want_ the return value packed together (though often, if that's what you really want, a struct might be better). And if you're not looking to assign the parts of a tuple to existing variables, then they're not quite as bad as when you are, since you don't necessarily have to then assign the pieces to other variables. Both have value, though if you need a lot of either, you should probably consider whether a struct or class would suit what you're doing better. - Jonathan M Davis
Re: Tuples citizenship
Jonathan M Davis: I'm sure that there are plenty of cases where using out parameters is actually far cleaner than using tuples, since you don't have multiple return values to deal with. Are you able to show me one or more examples where using one or more out arguments is in your opinion more clear (and safer!) than using a tuple with the proposed unpacking syntax? With a tuple you have to deal with multiple return values, but the semantics is cleaner (function = resulting tuple). The number of variables doesn't change, because with out you need to define them any way, before the call. If you think with tuples you lose the names of the out arguments there is a way to avoid this problem (but I don't know if in some situations out arguments are more efficient than tuples): pure nothrow @trusted real frexp(real value, out int exp); == pure nothrow @trusted Tuple!(real, int,exp) frexp(real value); Also, with a tuple result there is no risk of confusion if an argument is out (do you remember the discussion where people have asked a ref/out annotation at the calling point too, as in C#? With tuples this problem doesn't exists). Thank you for your answer, bye, bearophile
Re: Tuples citizenship
Jonathan M Davis jmdavisp...@gmx.com wrote: When you're looking to mutate existing variables in the caller, using out parameters results in cleaner code. Tuples are inherently messier, because you have to deal with multiple return values. They also often do poorly when you need to use the functional programming, because often you want all of the return values for later use but only want to pass _one_ of them to the function that you're passing the result to. You use 'ref' to mutate existing variable, not 'out'. Multiple return value doesn't replace the use case of ref. Not sure how messy it is to extract one value out of the tuple. It is much more messier to ignore an 'out' parameter than a field in a tuple in the call site. At other times, tuples are nicer - like when you actually _want_ the return value packed together (though often, if that's what you really want, a struct might be better). And if you're not looking to assign the parts of a tuple to existing variables, then they're not quite as bad as when you are, since you don't necessarily have to then assign the pieces to other variables. Both have value, though if you need a lot of either, you should probably consider whether a struct or class would suit what you're doing better. - Jonathan M Davis
Re: Tuples citizenship
Jonathan M Davis: When you're looking to mutate existing variables in the caller, using out parameters results in cleaner code. Tuples are inherently messier, because you have to deal with multiple return values. out arguments have two risks: - If you assign a value to a variable and then use it to call a function, the precedent value is ignored and overwritten. - If in a function you forget to assign an out argument, the D compiler produces no errors. Both source of bugs are not present with tuples. They also often do poorly when you need to use the functional programming, As you know functional languages use tuples all the time. At other times, tuples are nicer - like when you actually _want_ the return value packed together (though often, if that's what you really want, a struct might be better). Defining a struct makes your code messier. D tuples support named fields too, so the advantage of using a struct is limited. And if you're not looking to assign the parts of a tuple to existing variables, then they're not quite as bad as when you are, since you don't necessarily have to then assign the pieces to other variables. There are parts of your post that I don't fully understand. Both have value, though if you need a lot of either, you should probably consider whether a struct or class would suit what you're doing better. For most usages of a tuple a class instance means useless heap activity and more work for the GC. Using a struct to return the results of a function is sometimes acceptable, but most times I don't use tuples for that purpose. Consider this code in my original post, defining two static structs doesn't do much good to such kind of code: Tuple!(char,int)[] pairs2 = frequences.pairs; schwartzSort!(c_f = tuple(-c_f[1], c_f[0]))(pairs2); foreach (c_f; pairs2) writeln(c_f[1], , c_f[0]); Tuples are often defined and used on the fly, in-place. Bye, bearophile
Re: Tuples citizenship
On Thursday, March 01, 2012 18:57:15 bearophile wrote: Jonathan M Davis: They also often do poorly when you need to use the functional programming, As you know functional languages use tuples all the time. Yes, but chaining functions is the issue. It doesn't work well with tuples unless the function you're passing the result to wants the tuple. If all it wants is one piece of the tuple, then that doesn't work well at all. You're forced to assign the tuple to something else and then call then function rather than chain calls. That's one of the reasons that you constantly end up using stuff like let expressions and pattern matching in functional languages. You don't _want_ a tuple. Dealing with a tuple is annoying. It's just that it's often the best tool that you have to pass disparate stuff around, so that's what you use. And if you're not looking to assign the parts of a tuple to existing variables, then they're not quite as bad as when you are, since you don't necessarily have to then assign the pieces to other variables. There are parts of your post that I don't fully understand. It is often really annoying to have to deal with tuple return values, because you have to worry about unpacking the result. I don't want to use a tuple in the caller. Tuples are generally for grouping unrelated data that you don't necessarily want to keep togother (since if you did, you'd generally use a struct). I want the result to actually be assigned to variables. That is definitely cleaner with out than with tuples. int exp; auto result = frexp(value, exp); vs auto tup = frexp(value); result = tup[0]; exp = tup[1]; Getting tuple return values is annoying. Yes, it can be useful, but most stuff doesn't operate on tuples. It operates on the pieces of tuples. So, you have to constantly break them up. So, using out results in much nicer code. It always feels like I'm fighting the code when I have to deal with tuple return values. - Jonathan M Davis
Re: Tuples citizenship
Jonathan M Davis: Yes, but chaining functions is the issue. It doesn't work well with tuples unless the function you're passing the result to wants the tuple. If all it wants is one piece of the tuple, then that doesn't work well at all. You're forced to assign the tuple to something else and then call then function rather than chain calls. In the years I have used a mountain of tuples in Python, but I barely perceive that problem, so I think it's not so bad. int exp; auto result = frexp(value, exp); vs auto tup = frexp(value); result = tup[0]; exp = tup[1]; I have assumed to use a sane tuple unpacking syntax. So the second part of your comparison is: immutable (result, exp) = frexp(value); That is better than your version with the out argument, safer, looks better, and you are even able to make both results constant. Getting tuple return values is annoying. Yes, it can be useful, but most stuff doesn't operate on tuples. It operates on the pieces of tuples. So, you have to constantly break them up. So, using out results in much nicer code. I think that the tuple unpacking syntax is able to avoid part of your problems. The point of my original post, that maybe was lost in the bulk of the text, was that an unpacking syntax sugar is very useful if you want to use tuples for real in D. Bye and thank you, bearophile
Re: Tuples citizenship
On 02.03.2012 6:06, bearophile wrote: Jonathan M Davis: Yes, but chaining functions is the issue. It doesn't work well with tuples unless the function you're passing the result to wants the tuple. If all it wants is one piece of the tuple, then that doesn't work well at all. just stick in .expand ? void f(int x, int y){ } void main() { Tuple!(int, int) a; f(a.expand); } BTW it's nowhere to be found here http://dlang.org/phobos/std_typecons.html You're forced to assign the tuple to something else and then call then function rather than chain calls. In the years I have used a mountain of tuples in Python, but I barely perceive that problem, so I think it's not so bad. int exp; auto result = frexp(value, exp); vs auto tup = frexp(value); result = tup[0]; exp = tup[1]; I have assumed to use a sane tuple unpacking syntax. So the second part of your comparison is: immutable (result, exp) = frexp(value); That is better than your version with the out argument, safer, looks better, and you are even able to make both results constant. +1 Getting tuple return values is annoying. Yes, it can be useful, but most stuff doesn't operate on tuples. It operates on the pieces of tuples. So, you have to constantly break them up. So, using out results in much nicer code. I think that the tuple unpacking syntax is able to avoid part of your problems. s/part/most I'd say that results clearly belond to the left side of x = fun(...) expression, and tuples + unpack syntax are the way to make it consistent. With all sugar going on around Tuples, e.g. .tupleof, unpacking, I can't help but wonder why are they not built-ins. At least they should go to object.d/druntime like AA do. -- Dmitry Olshansky
Re: Tuples, C#, Java, language design
bearophile Wrote: C# will probably not follow the route of stagnation of Java for some more time, thanks to Mono too. I don't like that string interpolation syntax because it looks unsafe, and that design of tuples can be improved, but they are listening to programmes (even if they risk creating a mudball language): http://www.infoq.com/news/2009/12/Mono-CSharp-Ex More on those tuples: http://tirania.org/blog/archive/2009/Dec-23.html Eventually it will be quite useful to have some very well designed multi-return support in D (like those tuples, but better). Doesn't D2 already have tuples in Phobos. D has the comma operator which C# doesn't so such syntax is not possible in D, me thinks.
Re: Tuples, C#, Java, language design
justme wrote: bearophile Wrote: C# will probably not follow the route of stagnation of Java for some more time, thanks to Mono too. I don't like that string interpolation syntax because it looks unsafe, and that design of tuples can be improved, but they are listening to programmes (even if they risk creating a mudball language): http://www.infoq.com/news/2009/12/Mono-CSharp-Ex More on those tuples: http://tirania.org/blog/archive/2009/Dec-23.html Eventually it will be quite useful to have some very well designed multi-return support in D (like those tuples, but better). Doesn't D2 already have tuples in Phobos. D has the comma operator which C# doesn't so such syntax is not possible in D, me thinks. But tuples in D really suck. Compared to other languages, D tuples feel inflexible, stiff, and complicated.
Re: Tuples, C#, Java, language design
grauzone Wrote: justme wrote: bearophile Wrote: C# will probably not follow the route of stagnation of Java for some more time, thanks to Mono too. I don't like that string interpolation syntax because it looks unsafe, and that design of tuples can be improved, but they are listening to programmes (even if they risk creating a mudball language): http://www.infoq.com/news/2009/12/Mono-CSharp-Ex More on those tuples: http://tirania.org/blog/archive/2009/Dec-23.html Eventually it will be quite useful to have some very well designed multi-return support in D (like those tuples, but better). Doesn't D2 already have tuples in Phobos. D has the comma operator which C# doesn't so such syntax is not possible in D, me thinks. But tuples in D really suck. Compared to other languages, D tuples feel inflexible, stiff, and complicated. The burden of proving your claims is still there. Isn't D meritocracy - nobody listens your opinions unless you post compiler / stdlib patches. I believe the Phobos tuple classes are sufficient until a better system arrives in D3 or D4. D2 book is almost finished so you need to write your patches against D3 now.
Re: Tuples, C#, Java, language design
justme wrote: grauzone Wrote: justme wrote: bearophile Wrote: C# will probably not follow the route of stagnation of Java for some more time, thanks to Mono too. I don't like that string interpolation syntax because it looks unsafe, and that design of tuples can be improved, but they are listening to programmes (even if they risk creating a mudball language): http://www.infoq.com/news/2009/12/Mono-CSharp-Ex More on those tuples: http://tirania.org/blog/archive/2009/Dec-23.html Eventually it will be quite useful to have some very well designed multi-return support in D (like those tuples, but better). Doesn't D2 already have tuples in Phobos. D has the comma operator which C# doesn't so such syntax is not possible in D, me thinks. But tuples in D really suck. Compared to other languages, D tuples feel inflexible, stiff, and complicated. The burden of proving your claims is still there. Isn't D meritocracy - nobody listens your opinions unless you post compiler / stdlib patches. I believe the Phobos tuple classes are sufficient until a better system arrives in D3 or D4. D2 book is almost finished so you need to write your patches against D3 now. My experience with patches is, that they're mostly either ignored or rejected. I guess the chance of an unrequested patch changing a core language feature in crucial ways is 200%. Walter doesn't listen to anyone anyway *g*. The downsides of D tuples has been often mentioned, e.g. here: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.Darticle_id=98953 (Sorry, I'm not as eloquent as language_fan to write it up myself, plus nobody would read it.)
Re: tuples
Ellery Newcomer Wrote: Is there currently any way to get something like Tuple!(int,i) t = tuple(5); to work? Tuples are compile-time constructions. They are immutable. And btw the types do not coincide
Re: tuples
Ellery Newcomer wrote: Is there currently any way to get something like Tuple!(int,i) t = tuple(5); to work? Doh. It looks like Tuple!(int,i) t = tuple!(int,i)(5); should work, but I'm getting the following error /home/ellery/download/dmd2035/dmd2/linux/bin/../../src/phobos/std/typecons.d(514): Error: template std.typecons.tuple(T...) declaration T is already defined any ideas?
Re: tuples
Ellery Newcomer Wrote: Ellery Newcomer wrote: Is there currently any way to get something like Tuple!(int,i) t = tuple(5); to work? Doh. It looks like Tuple!(int,i) t = tuple!(int,i)(5); should work, but I'm getting the following error /home/ellery/download/dmd2035/dmd2/linux/bin/../../src/phobos/std/typecons.d(514): Error: template std.typecons.tuple(T...) declaration T is already defined any ideas? Ah that std.typecons tuple, not the variadic template tuple; I assume you are trying to initialize the tuple like Tuple!(int,i) t = tuple!(5); if it is not, what are you trying to do?
Re: tuples
On Fri, Jun 12, 2009 at 12:10 AM, Ellery Newcomerellery-newco...@utulsa.edu wrote: what is up with this code? auto t = tuple(1,'a',3.333,false); pragma(msg,typeof(t.tupleof[2 .. $]).stringof); spits out (double, bool, int, char, double, bool) It has to do with the way Tuple is implemented in std.typecons: union { Types field; mixin(tupleFields!(0, T)); } field is of type (double, bool, int, char), and the mixin defines something like struct { double _0; bool _1; int _2; char _3; }. Since it's a union, the field member overlaps with the anonymous struct, just giving you two different ways of accessing the same member: t.field[0] or t._0. When DMD does the tupleof, it puts all the union members in the tuple, giving you what looks like a duplicated type list. You can instead use: pragma(msg,typeof(t.field[$ - 2 .. $]).stringof);
Re: tuples
On Fri, Jun 12, 2009 at 11:00 AM, Jarrett Billingsleyjarrett.billings...@gmail.com wrote: On Fri, Jun 12, 2009 at 12:10 AM, Ellery Newcomerellery-newco...@utulsa.edu wrote: what is up with this code? auto t = tuple(1,'a',3.333,false); pragma(msg,typeof(t.tupleof[2 .. $]).stringof); spits out (double, bool, int, char, double, bool) It has to do with the way Tuple is implemented in std.typecons: union { Types field; mixin(tupleFields!(0, T)); } field is of type (double, bool, int, char), and the mixin defines something like struct { double _0; bool _1; int _2; char _3; }. Since it's a union, the field member overlaps with the anonymous struct, just giving you two different ways of accessing the same member: t.field[0] or t._0. When DMD does the tupleof, it puts all the union members in the tuple, giving you what looks like a duplicated type list. You can instead use: pragma(msg,typeof(t.field[$ - 2 .. $]).stringof); Er, pragma(msg,typeof(t.field[2 .. $]).stringof);
Re: tuples
what is up with this code? auto t = tuple(1,'a',3.333,false); pragma(msg,typeof(t.tupleof[2 .. $]).stringof); spits out (double, bool, int, char, double, bool) template Tuple(E...) { alias E Tuple; } alias Tuple!(1,'a',3.333,false) t; pragma(msg,typeof(t.tupleof[2 .. $]).stringof); //Error pragma(msg,typeof(t[2..$].stringof); //writes (double, bool)
Re: Tuples
Reply to dsimcha, I've been thinking a little about the idea of returning tuples from functions, w.r.t. Bugzilla 2628 (http://d.puremagic.com/issues/show_bug.cgi?id=2628). Would it be feasible to solve this by making struct[index] for any struct w/o an opIndex overload equivalent to struct.tupleof[index]? This would be trivial syntactic sugar, but would allow user-defined tuples in Phobos to look like a builtin tuple, be returned from functions, etc., while changing very little under the hood. Furthermore, for functions that take a tuple, we could allow structs to be implicitly cast to tuples, e.g.: struct Foo { uint u; float f; } void doStuff(uint myInt, float myFloat) {} Foo foo; doStuff(foo); // Implicitly casts to foo.tupleof, works. I like the first part some (but not without reservations). As for the second bit... I don't like it. It would make overload resolution to tricky, if not at the compiler level than at the eyeball level.
Re: Tuples
== Quote from BCS (a...@pathlink.com)'s article Reply to dsimcha, I've been thinking a little about the idea of returning tuples from functions, w.r.t. Bugzilla 2628 (http://d.puremagic.com/issues/show_bug.cgi?id=2628). Would it be feasible to solve this by making struct[index] for any struct w/o an opIndex overload equivalent to struct.tupleof[index]? This would be trivial syntactic sugar, but would allow user-defined tuples in Phobos to look like a builtin tuple, be returned from functions, etc., while changing very little under the hood. Furthermore, for functions that take a tuple, we could allow structs to be implicitly cast to tuples, e.g.: struct Foo { uint u; float f; } void doStuff(uint myInt, float myFloat) {} Foo foo; doStuff(foo); // Implicitly casts to foo.tupleof, works. I like the first part some (but not without reservations). As for the second bit... I don't like it. It would make overload resolution to tricky, if not at the compiler level than at the eyeball level. Yeah, scratch the second part. In addition, I thought of this problem after I posted: struct Foo { uint u; float f; } void doStuff(T...)(T args) {} Foo foo; doStuff(foo); // Ambiguous. Does the struct get passed, or is it //unpacked to a tuple?
Re: Tuples
BCS wrote: Reply to dsimcha, I've been thinking a little about the idea of returning tuples from functions, w.r.t. Bugzilla 2628 (http://d.puremagic.com/issues/show_bug.cgi?id=2628). Would it be feasible to solve this by making struct[index] for any struct w/o an opIndex overload equivalent to struct.tupleof[index]? This would be trivial syntactic sugar, but would allow user-defined tuples in Phobos to look like a builtin tuple, be returned from functions, etc., while changing very little under the hood. Furthermore, for functions that take a tuple, we could allow structs to be implicitly cast to tuples, e.g.: struct Foo { uint u; float f; } void doStuff(uint myInt, float myFloat) {} Foo foo; doStuff(foo); // Implicitly casts to foo.tupleof, works. I like the first part some (but not without reservations). As for the second bit... I don't like it. It would make overload resolution to tricky, if not at the compiler level than at the eyeball level. I personally believe this is all getting a bit too silly; it's all this work to get around that you can't return tuples from a function. I think it'd be a better idea to just make it so we can return value tuples from functions, period. Of course, I also want automatic unpacking and to re-purpose that silly comma operator, but that can wait. :) As for the second, I just use this: Foo foo; doStuff(foo.tupleof); Note: it's been a while, and I might have used a special .tuple member; can't remember. -- Daniel