digitalmars.D.learn - Should formattedWrite take the outputrange by ref?
- Tobias Pankrath (9/9) Jan 18 2014 I want to print a tree structure and need to keep track of the
- monarch_dodra (5/15) Jan 18 2014 *I* think it should. File a report, and I'll see what I can do
- bearophile (6/9) Jan 18 2014 Given the frequency of bugs caused by such functions that require
- Tobias Pankrath (3/12) Jan 18 2014 I actually didn't think that a ptr (to output range) would work.
- monarch_dodra (19/22) Jan 19 2014 A fun fact is that since "." notation works with pointers, more
- Tobias Pankrath (5/7) Jan 19 2014 Or a special template constraint path for T*.
- Tobias Pankrath (7/15) Jan 19 2014 But maybe we really should go for taking the output range by
- monarch_dodra (2/23) Jan 19 2014 Thanks! I'll look into these.
- Guillaume Chatelet (1/1) Sep 03 2014 +1 I've been bitten by this also.
- =?UTF-8?B?Ik3DoXJjaW8=?= Martins" (3/4) Sep 04 2014 Same here, +1
- monarch_dodra (5/9) Sep 04 2014 It's still on my radar, but it's actually not that trivial of a
- anonymous (3/11) Jan 18 2014 Alternatively, pass a pointer: formattedWrite(&writer, ...)
I want to print a tree structure and need to keep track of the indention for different parts of the tree. My idea was to write a generic wrapper for an output range that outputs tabs when it encounters a newline. This wrapper has internal state and if I want to use formattedWrite with this wrapper than state changes don't propagate to the calling context because by value semantics. Short solution: I'm using a class now. But shouldn't formattedWrite take it's output range by ref? Does anyone else have a use case for this and might this cause any problems?
Jan 18 2014
On Saturday, 18 January 2014 at 21:55:54 UTC, Tobias Pankrath wrote:I want to print a tree structure and need to keep track of the indention for different parts of the tree. My idea was to write a generic wrapper for an output range that outputs tabs when it encounters a newline. This wrapper has internal state and if I want to use formattedWrite with this wrapper than state changes don't propagate to the calling context because by value semantics. Short solution: I'm using a class now. But shouldn't formattedWrite take it's output range by ref? Does anyone else have a use case for this and might this cause any problems?*I* think it should. File a report, and I'll see what I can do about it. The problem with these kinds of things though might be breaking existing code...
Jan 18 2014
monarch_dodra:*I* think it should. File a report, and I'll see what I can do about it. The problem with these kinds of things though might be breaking existing code...Given the frequency of bugs caused by such functions that require a pointer to the data, I think that a breaking change is the smaller problem. Bye, bearophile
Jan 18 2014
On Saturday, 18 January 2014 at 22:58:59 UTC, bearophile wrote:monarch_dodra:I actually didn't think that a ptr (to output range) would work. This way we can have best of both worlds and I'm happy with it.*I* think it should. File a report, and I'll see what I can do about it. The problem with these kinds of things though might be breaking existing code...Given the frequency of bugs caused by such functions that require a pointer to the data, I think that a breaking change is the smaller problem. Bye, bearophile
Jan 18 2014
On Saturday, 18 January 2014 at 23:06:42 UTC, Tobias Pankrath wrote:I actually didn't think that a ptr (to output range) would work. This way we can have best of both worlds and I'm happy with it.A fun fact is that since "." notation works with pointers, more often than not, if "T" verifies some trait "isOutputRange", more often than not, so will "T*". But this is more of a by-product than an actual rule, and, as a rule of thumb, may not be something you want to rely on in a general sense. Limitations include: Type checking: If "R" is a random access range, "R*" will only be an input range, because "p.save" will return an "R", and not an "R*" :/ Also, it is limited to member functions, and not generic UFCS: For example, while in the general sense, "R is input range" => "R* is input range", this will fail for "T[]*", because slices have a non-member popFront, so "p.popFront()" will not actually match a function, and "T[]*" will fail the input range validation :/ So, my conclusion, "*" might be a workable solution. But simply taking by ref would be cleaner, and make more sense as a whole.
Jan 19 2014
On Sunday, 19 January 2014 at 15:03:13 UTC, monarch_dodra wrote:So, my conclusion, "*" might be a workable solution. But simply taking by ref would be cleaner, and make more sense as a whole.Or a special template constraint path for T*. foo(T)(T t) if (is(T = Q*)) && manyOtherChecks!(Q) foo(T)(T t) if (!is(T = Q*)) && manyOtherChecks!(T) Maybe that will break less code.
Jan 19 2014
On Sunday, 19 January 2014 at 15:12:07 UTC, Tobias Pankrath wrote:On Sunday, 19 January 2014 at 15:03:13 UTC, monarch_dodra wrote:But maybe we really should go for taking the output range by reference. See https://d.puremagic.com/issues/show_bug.cgi?id=10291 https://d.puremagic.com/issues/show_bug.cgi?id=9102 Created a new report for this: https://d.puremagic.com/issues/show_bug.cgi?id=11951So, my conclusion, "*" might be a workable solution. But simply taking by ref would be cleaner, and make more sense as a whole.Or a special template constraint path for T*. foo(T)(T t) if (is(T = Q*)) && manyOtherChecks!(Q) foo(T)(T t) if (!is(T = Q*)) && manyOtherChecks!(T) Maybe that will break less code.
Jan 19 2014
On Sunday, 19 January 2014 at 15:28:04 UTC, Tobias Pankrath wrote:On Sunday, 19 January 2014 at 15:12:07 UTC, Tobias Pankrath wrote:Thanks! I'll look into these.On Sunday, 19 January 2014 at 15:03:13 UTC, monarch_dodra wrote:But maybe we really should go for taking the output range by reference. See https://d.puremagic.com/issues/show_bug.cgi?id=10291 https://d.puremagic.com/issues/show_bug.cgi?id=9102 Created a new report for this: https://d.puremagic.com/issues/show_bug.cgi?id=11951So, my conclusion, "*" might be a workable solution. But simply taking by ref would be cleaner, and make more sense as a whole.Or a special template constraint path for T*. foo(T)(T t) if (is(T = Q*)) && manyOtherChecks!(Q) foo(T)(T t) if (!is(T = Q*)) && manyOtherChecks!(T) Maybe that will break less code.
Jan 19 2014
+1 I've been bitten by this also.
Sep 03 2014
On Wednesday, 3 September 2014 at 07:43:20 UTC, Guillaume Chatelet wrote:+1 I've been bitten by this also.Same here, +1
Sep 04 2014
On Thursday, 4 September 2014 at 17:06:00 UTC, Márcio Martins wrote:On Wednesday, 3 September 2014 at 07:43:20 UTC, Guillaume Chatelet wrote:It's still on my radar, but it's actually not that trivial of a change, especially if we want to avoid breaking code, and binary bloat...+1 I've been bitten by this also.Same here, +1
Sep 04 2014
On Saturday, 18 January 2014 at 21:55:54 UTC, Tobias Pankrath wrote:I want to print a tree structure and need to keep track of the indention for different parts of the tree. My idea was to write a generic wrapper for an output range that outputs tabs when it encounters a newline. This wrapper has internal state and if I want to use formattedWrite with this wrapper than state changes don't propagate to the calling context because by value semantics. Short solution: I'm using a class now.Alternatively, pass a pointer: formattedWrite(&writer, ...)
Jan 18 2014