Re: pop & popFront combined
On Saturday, 1 November 2014 at 13:22:34 UTC, Nordlöw wrote: https://github.com/nordlow/justd/blob/master/range_ex.d#L14 Moved here: https://github.com/nordlow/phobos-next/blob/master/src/range_ex.d#L66
Re: pop popFront combined
On Saturday, 1 November 2014 at 14:19:56 UTC, Nordlöw wrote: On Saturday, 1 November 2014 at 13:54:31 UTC, Nordlöw wrote: On Saturday, 1 November 2014 at 13:38:22 UTC, Marc Schütz wrote: If you want to avoid the temporary variable, you could write: scope(success) r.popFront; return r.moveFront; Does this solution cost performance? I guess we have to look at the assembler output to be sure. Is there a convenient way to do this in LDC? ldc2 -O3 -output-s -c test.d Generates test.s.
Re: pop popFront combined
On Saturday, 1 November 2014 at 13:54:31 UTC, Nordlöw wrote: On Saturday, 1 November 2014 at 13:38:22 UTC, Marc Schütz wrote: If you want to avoid the temporary variable, you could write: scope(success) r.popFront; return r.moveFront; Does this solution cost performance? I think DMD doesn't generate good code for it; IIRC it lowers scope(success) to a strange construct with an invisible variable and a try/catch. Don't know the reasons for this, maybe it has changed by now. Theoretically it would just need to move the contents of the scope(success) after the evaluation of the returned expression, which is cheap.
Re: pop popFront combined
On Sunday, 2 November 2014 at 11:46:19 UTC, Marc Schütz wrote: I think DMD doesn't generate good code for it; IIRC it lowers scope(success) to a strange construct with an invisible variable and a try/catch. Don't know the reasons for this, maybe it has changed by now. Theoretically it would just need to move the contents of the scope(success) after the evaluation of the returned expression, which is cheap. Are there cases in LDC where auto e = r.moveFront; r.popFront; return e; generates code less efficient than scope(success) r.popFront; return r.moveFront; because of the extra assignment?
Re: pop popFront combined
On Sunday, 2 November 2014 at 12:29:14 UTC, Nordlöw wrote: On Sunday, 2 November 2014 at 11:46:19 UTC, Marc Schütz wrote: I think DMD doesn't generate good code for it; IIRC it lowers scope(success) to a strange construct with an invisible variable and a try/catch. Don't know the reasons for this, maybe it has changed by now. Theoretically it would just need to move the contents of the scope(success) after the evaluation of the returned expression, which is cheap. Are there cases in LDC where auto e = r.moveFront; r.popFront; return e; generates code less efficient than scope(success) r.popFront; return r.moveFront; because of the extra assignment? I'm not sure. If the element type has a postblit, there might be some obscure corner case where the language specification requires a copy if you declare a named variable. In general I would expect no (language level) copy to take place. The result of `moveFront` can just be moved into the yet uninitialized `e`, which later can be moved up to the caller. These are simple bitblits, not copies.
Re: pop popFront combined
On Saturday, 20 September 2014 at 19:23:46 UTC, Jakob Ovrum wrote: If you want move semantics, use `moveFront`. But x.moveFront doesn't modify x. What I want is to transform my uses of std.range from if (!x.empty) { x.front.doStuff; x.popFront; } into if (!x.empty) if (auto front = x.stealFront) { front.doStuff; } This is more functional/atomic, that is it reduces the risk of accidentally forgetting to call popFront at the end. Destroy!
Re: pop popFront combined
On Saturday, 1 November 2014 at 11:43:28 UTC, Nordlöw wrote: if (!x.empty) if (auto front = x.stealFront) { front.doStuff; } This is more functional/atomic, that is it reduces the risk of accidentally forgetting to call popFront at the end. Forgot my explicit question: So why isn't something like x.stealFront already in Phobos?
Re: pop popFront combined
On Saturday, 20 September 2014 at 19:40:02 UTC, AsmMan wrote: Is this function part of phobos library? if so, where? It's in std.range.
Re: pop popFront combined
On Saturday, 1 November 2014 at 11:45:25 UTC, Nordlöw wrote: So why isn't something like x.stealFront already in Phobos? First try here: https://github.com/nordlow/justd/blob/master/range_ex.d#L14 Please comment!
Re: pop popFront combined
On Saturday, 1 November 2014 at 13:22:34 UTC, Nordlöw wrote: https://github.com/nordlow/justd/blob/master/range_ex.d#L14 Please comment! What's the recommended way of making stealFront and stealBack inout here? Can I somehow use auto ref together with inout?
Re: pop popFront combined
On Saturday, 1 November 2014 at 13:22:34 UTC, Nordlöw wrote: On Saturday, 1 November 2014 at 11:45:25 UTC, Nordlöw wrote: So why isn't something like x.stealFront already in Phobos? First try here: https://github.com/nordlow/justd/blob/master/range_ex.d#L14 Please comment! That is: auto ref stealFront(R)(ref R r) { import std.range: moveFront, popFront; auto e = r.moveFront; r.popFront; return e; } `auto ref` is nonsense here. You can't return a reference to `e` as it's a local variable.
Re: pop popFront combined
On Saturday, 1 November 2014 at 13:25:03 UTC, Nordlöw wrote: On Saturday, 1 November 2014 at 13:22:34 UTC, Nordlöw wrote: https://github.com/nordlow/justd/blob/master/range_ex.d#L14 Please comment! What's the recommended way of making stealFront and stealBack inout here? Can I somehow use auto ref together with inout? I don't see what you'd need inout for here. stealFront/stealBack are not methods.
Re: pop popFront combined
On Saturday, 1 November 2014 at 13:30:16 UTC, anonymous wrote: On Saturday, 1 November 2014 at 13:22:34 UTC, Nordlöw wrote: On Saturday, 1 November 2014 at 11:45:25 UTC, Nordlöw wrote: So why isn't something like x.stealFront already in Phobos? First try here: https://github.com/nordlow/justd/blob/master/range_ex.d#L14 Please comment! That is: auto ref stealFront(R)(ref R r) { import std.range: moveFront, popFront; auto e = r.moveFront; r.popFront; return e; } `auto ref` is nonsense here. You can't return a reference to `e` as it's a local variable. It's probably intended to mean `auto` + `ref`, not `auto ref`. `ref` alone is already sufficient to get type deduction.
Re: pop popFront combined
On Saturday, 1 November 2014 at 13:36:05 UTC, Marc Schütz wrote: On Saturday, 1 November 2014 at 13:30:16 UTC, anonymous wrote: [...] auto ref stealFront(R)(ref R r) { import std.range: moveFront, popFront; auto e = r.moveFront; r.popFront; return e; } [...] It's probably intended to mean `auto` + `ref`, not `auto ref`. `ref` alone is already sufficient to get type deduction. But ref is wrong. The function returns a local. Just auto would be fine.
Re: pop popFront combined
On Saturday, 1 November 2014 at 13:25:03 UTC, Nordlöw wrote: On Saturday, 1 November 2014 at 13:22:34 UTC, Nordlöw wrote: https://github.com/nordlow/justd/blob/master/range_ex.d#L14 Please comment! What's the recommended way of making stealFront and stealBack inout here? Can I somehow use auto ref together with inout? If you want to avoid the temporary variable, you could write: scope(success) r.popFront; return r.moveFront;
Re: pop popFront combined
On Saturday, 1 November 2014 at 13:38:22 UTC, Marc Schütz wrote: If you want to avoid the temporary variable, you could write: scope(success) r.popFront; return r.moveFront; Does this solution cost performance?
Re: pop popFront combined
On Saturday, 1 November 2014 at 13:30:16 UTC, anonymous wrote: `auto ref` is nonsense here. You can't return a reference to `e` as it's a local variable. My mistake. Thanks.
Re: pop popFront combined
On Saturday, 1 November 2014 at 13:36:05 UTC, anonymous wrote: I don't see what you'd need inout for here. stealFront/stealBack are not methods. inout can be used on free functions aswell. See for example https://github.com/nordlow/justd/blob/master/algorithm_ex.d#L674
Re: pop popFront combined
On Saturday, 1 November 2014 at 14:01:42 UTC, Nordlöw wrote: On Saturday, 1 November 2014 at 13:36:05 UTC, anonymous wrote: I don't see what you'd need inout for here. stealFront/stealBack are not methods. inout can be used on free functions aswell. See for example https://github.com/nordlow/justd/blob/master/algorithm_ex.d#L674 Sure, but it doesn't buy you anything in these cases, does it? You can just drop inout from overlapInOrder. It's fully templated. T can be const/immutable and you get a const/immutable result. Works fine.
Re: pop popFront combined
On Saturday, 1 November 2014 at 11:43:28 UTC, Nordlöw wrote: On Saturday, 20 September 2014 at 19:23:46 UTC, Jakob Ovrum wrote: If you want move semantics, use `moveFront`. But x.moveFront doesn't modify x. It does modify `x` as it leaves `front` in a destroyed and default-initialized state, as required by move semantics. What I want is to transform my uses of std.range from if (!x.empty) { x.front.doStuff; x.popFront; } into if (!x.empty) if (auto front = x.stealFront) { front.doStuff; } This is more functional/atomic, that is it reduces the risk of accidentally forgetting to call popFront at the end. Destroy! The other half of my post explained why such a `stealFront` is problematic.
Re: pop popFront combined
On Saturday, 1 November 2014 at 16:10:17 UTC, Jakob Ovrum wrote: The other half of my post explained why such a `stealFront` is problematic. Got it. Thanks!
Re: pop popFront combined
On Saturday, 20 September 2014 at 19:23:46 UTC, Jakob Ovrum wrote: Sometimes after popping, the previous `front` is no longer valid, such as in the case of a buffer being reused. We should This seems like a error-prone design to me. I guess performance is the motivation right? Maybe a future data-flow analysis á lá Rust could come to the rescue here ;)
Re: pop popFront combined
On Saturday, 20 September 2014 at 19:23:46 UTC, Jakob Ovrum wrote: Sometimes after popping, the previous `front` is no longer valid, such as in the case of a buffer being reused. Is there a suitable trait we can use to detect this and in turn use to disallow stealFront() and stealBack() in these cases? We should be careful about promoting using a previously read `front` after `popFront` until we figure out what we want to do about these transient ranges.
Re: pop popFront combined
On Saturday, 1 November 2014 at 16:10:17 UTC, Jakob Ovrum wrote: problematic. What about turning stealFront and stealBack at https://github.com/nordlow/justd/blob/master/range_ex.d into mixins?
Re: pop popFront combined
On Saturday, 1 November 2014 at 20:48:45 UTC, Nordlöw wrote: Is there a suitable trait we can use to detect this and in turn use to disallow stealFront() and stealBack() in these cases? Made it a separate new question at http://forum.dlang.org/thread/onibkzepudfisxtri...@forum.dlang.org#post-onibkzepudfisxtrigsi:40forum.dlang.org
pop popFront combined
Is there a reason why popFront doesn't automatically return what front does? If so I'm still missing a combined variant of pop and popFront in std.range. Why isn't such a common operation in Phobos already?
Re: pop popFront combined
On Saturday, 20 September 2014 at 18:59:03 UTC, Nordlöw wrote: Is there a reason why popFront doesn't automatically return what front does? If so I'm still missing a combined variant of pop and popFront in std.range. Why isn't such a common operation in Phobos already? Sometimes after popping, the previous `front` is no longer valid, such as in the case of a buffer being reused. We should be careful about promoting using a previously read `front` after `popFront` until we figure out what we want to do about these transient ranges. If you want move semantics, use `moveFront`.
Re: pop popFront combined
On Saturday, 20 September 2014 at 18:59:03 UTC, Nordlöw wrote: Is there a reason why popFront doesn't automatically return what front does? If so I'm still missing a combined variant of pop and popFront in std.range. Why isn't such a common operation in Phobos already? So far I know isn't common use return value from popFront() at same time it's called. For example, checkout how is: int[] a = [1,2,3]; foreach(int n; a) {} is translated: for(auto r = a; !r.empty; r.popFront()) { int n = r.front; } to return same as value in front by popFront() save previously value is needed: int popFrontInt(out int[] arr) { int current = arr[0]; // or arr.front arr = arr[1 .. $]; return current; } (this isn't exactly like Phobos implementation and is int[]-only, btw) the cost of the 'current' variable may be a bit expansive (one extra register use per function call) and useless, since it isn't used and a common use is one like the loop. I think it's well-designed, IMHO... On Saturday, 20 September 2014 at 18:59:03 UTC, Nordlöw wrote: If you want move semantics, use `moveFront`. Is this function part of phobos library? if so, where?
Re: pop popFront combined
On Saturday, 20 September 2014 at 19:23:46 UTC, Jakob Ovrum wrote: Sometimes after popping, the previous `front` is no longer valid, such as in the case of a buffer being reused. We should be careful about promoting using a previously read `front` after `popFront` until we figure out what we want to do about these transient ranges. If you want move semantics, use `moveFront`. Excellent! Thanks!
Re: pop popFront combined
On 09/20/2014 11:59 AM, Nordlöw wrote: Is there a reason why popFront doesn't automatically return what front does? If so I'm still missing a combined variant of pop and popFront in std.range. Why isn't such a common operation in Phobos already? It is also related to exception safety. It took the C++ community to realize that a Stack data structure with pop() returning the top object cannot be made exception safe. The solution was to separate pop() from top(). Here is the original paper demonstrating the impossibility: http://ptgmedia.pearsoncmg.com/imprint_downloads/informit/aw/meyerscddemo/DEMO/MAGAZINE/CA_FRAME.HTM Here is Herb Sutter's presentation of the solution: http://www.gotw.ca/gotw/008.htm Ali