Thread overview | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 30, 2017 std.range.interfaces : InputRange moveFront | ||||
---|---|---|---|---|
| ||||
What does the moveFront() method do in the InputRange interface? std.range.interfaces : InputRange.moveFront() |
November 29, 2017 Re: std.range.interfaces : InputRange moveFront | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tony | On 11/29/2017 08:31 PM, Tony wrote:
> What does the moveFront() method do in the InputRange interface?
>
> std.range.interfaces : InputRange.moveFront()
move is an operation that transfers the state of the source to the destination. The front element becomes its .init value and its previous values is returned by moveFront().
The important bit is that, the element is *not* copied:
import std.range;
struct S {
int i;
bool is_a_copy = false;
this(this) {
is_a_copy = true;
}
}
void main() {
auto r = [S(1)];
auto a = r.front;
assert(a.is_a_copy); // yes, a is a copy
assert(a.i == 1); // as expected, 1
assert(r.front.i == 1); // front is still 1
auto b = r.moveFront();
assert(!b.is_a_copy); // no, b is not a copy
assert(b.i == 1); // state is transferred
assert(r.front.i == 0); // front is int.init
}
Ali
|
November 30, 2017 Re: std.range.interfaces : InputRange moveFront | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 30 November 2017 at 06:36:12 UTC, Ali Çehreli wrote:
>
> move is an operation that transfers the state of the source to the destination. The front element becomes its .init value and its previous values is returned by moveFront().
>
> The important bit is that, the element is *not* copied:
>
> import std.range;
>
> struct S {
> int i;
> bool is_a_copy = false;
> this(this) {
> is_a_copy = true;
> }
> }
>
> void main() {
> auto r = [S(1)];
>
> auto a = r.front;
> assert(a.is_a_copy); // yes, a is a copy
> assert(a.i == 1); // as expected, 1
> assert(r.front.i == 1); // front is still 1
>
> auto b = r.moveFront();
> assert(!b.is_a_copy); // no, b is not a copy
> assert(b.i == 1); // state is transferred
> assert(r.front.i == 0); // front is int.init
> }
>
Thanks for the reply. Probably just missing it, but in poking around dlang.org (Language Reference and Library Reference) I am having trouble finding out about the move(), front() and moveFront() functions, as is used here on a dynamic array.
|
November 30, 2017 Re: std.range.interfaces : InputRange moveFront | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tony | On Thursday, 30 November 2017 at 09:47:14 UTC, Tony wrote:
> Thanks for the reply. Probably just missing it, but in poking around dlang.org (Language Reference and Library Reference) I am having trouble finding out about the move(), front() and moveFront() functions, as is used here on a dynamic array.
That should just be front() and moveFront() used here. I ran across move() in looking at the standard library for the definitions of the other two.
|
November 30, 2017 Re: std.range.interfaces : InputRange moveFront | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tony | On Thursday, 30 November 2017 at 09:50:37 UTC, Tony wrote: > On Thursday, 30 November 2017 at 09:47:14 UTC, Tony wrote: > >> Thanks for the reply. Probably just missing it, but in poking around dlang.org (Language Reference and Library Reference) I am having trouble finding out about the move(), front() and moveFront() functions, as is used here on a dynamic array. > > That should just be front() and moveFront() used here. I ran across move() in looking at the standard library for the definitions of the other two. Found a move() here: https://dlang.org/library/std/algorithm/mutation/move.html Function std.algorithm.mutation.move |
November 30, 2017 Re: std.range.interfaces : InputRange moveFront | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tony | On 11/30/2017 07:31 AM, Tony wrote: > On Thursday, 30 November 2017 at 09:50:37 UTC, Tony wrote: >> On Thursday, 30 November 2017 at 09:47:14 UTC, Tony wrote: >> >>> Thanks for the reply. Probably just missing it, but in poking around dlang.org (Language Reference and Library Reference) I am having trouble finding out about the move(), front() and moveFront() functions, as is used here on a dynamic array. >> >> That should just be front() and moveFront() used here. I ran across move() in looking at the standard library for the definitions of the other two. > > Found a move() here: > https://dlang.org/library/std/algorithm/mutation/move.html > Function std.algorithm.mutation.move I don't know why it isn't listed at the top of the page but front() for arrays is here: https://dlang.org/phobos/std_range_primitives.html#.front And moveFront(): https://dlang.org/phobos/std_range_primitives.html#.moveFront Ali |
December 01, 2017 Re: std.range.interfaces : InputRange moveFront | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 30 November 2017 at 06:36:12 UTC, Ali Çehreli wrote:
>
> import std.range;
>
> struct S {
> int i;
> bool is_a_copy = false;
> this(this) {
> is_a_copy = true;
> }
> }
>
> void main() {
> auto r = [S(1)];
>
> auto a = r.front;
> assert(a.is_a_copy); // yes, a is a copy
> assert(a.i == 1); // as expected, 1
> assert(r.front.i == 1); // front is still 1
>
> auto b = r.moveFront();
> assert(!b.is_a_copy); // no, b is not a copy
> assert(b.i == 1); // state is transferred
> assert(r.front.i == 0); // front is int.init
> }
I tested it and it works like you wrote, but the behavior is different for an array of integers...:
auto a = [ 1,2,3 ];
writeln(a.front); // 1
auto b = a.moveFront();
writeln(b); // 1
writeln(a.length); // still 3
writeln(a.front); // still 1
-Johan
|
December 01, 2017 Re: std.range.interfaces : InputRange moveFront | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johan Engelen | On Friday, 1 December 2017 at 09:11:40 UTC, Johan Engelen wrote:
>
> I tested it and it works like you wrote, but the behavior is different for an array of integers...:
Hmm, I guess I misread what Ali meant. But the documentation is wrong/very confusing for moveFront:
It says "moveFront -- Removes the front element of a range." and "Moves the front of r out and returns it." With "to move _out_", I would expect that the range is advanced/shortened/..., but it is not.
(Also, I would expect "popFront" to return the element popped, but it doesn't, OK...
So which function name is given to the behavior of "pop" of other languages?)
-Johan
|
December 01, 2017 Re: std.range.interfaces : InputRange moveFront | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johan Engelen | On 12/1/17 4:29 AM, Johan Engelen wrote: > On Friday, 1 December 2017 at 09:11:40 UTC, Johan Engelen wrote: >> >> I tested it and it works like you wrote, but the behavior is different for an array of integers...: > > Hmm, I guess I misread what Ali meant. But the documentation is wrong/very confusing for moveFront: > It says "moveFront -- Removes the front element of a range." and "Moves the front of r out and returns it." With "to move _out_", I would expect that the range is advanced/shortened/..., but it is not. move is supposed to move the bits from one place to another (i.e. without calling any constructor or postblit). It doesn't destroy the existence of the original, it's supposed to leave it as an empty shell (read: set the original to it's .init value). However, I'm surprised the front element is still 1. I would think it should be int.init. But I guess it makes sense that if a type doesn't have a destructor, there's no need to worry about initializing it. move probably doesn't care if it's a value type without a destructor. > (Also, I would expect "popFront" to return the element popped, but it doesn't, OK... pop removes the front element, but if getting the front element is expensive (say if it's a map with a complex lambda function), you don't want to execute that just so you can return it to someone who doesn't care. This is why front and popFront are separate. > So which function name is given to the behavior of "pop" of other languages?) Nothing. You have to do both front and popFront. Others have proposed a wrapper that does both, but in order to truly take advantage of the fact that you are removing and calculating the front value at the same time, you need a new range type. Some have suggested that too. -Steve |
December 01, 2017 Re: std.range.interfaces : InputRange moveFront | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johan Engelen | On 12/01/2017 01:11 AM, Johan Engelen wrote: > I tested it and it works like you wrote, but the behavior is different for an array of integers...: > > auto a = [ 1,2,3 ]; > writeln(a.front); // 1 > auto b = a.moveFront(); > writeln(b); // 1 > writeln(a.length); // still 3 > writeln(a.front); // still 1 > > -Johan Good catch, which affects my struct S example as well. It's a documentation bug as it does not mention different behavior depending on elaborate copy constructor: https://github.com/dlang/phobos/blob/master/std/range/primitives.d#L1848 ElementType!R moveFront(R)(R r) { static if (is(typeof(&r.moveFront))) { return r.moveFront(); } else static if (!hasElaborateCopyConstructor!(ElementType!R)) { return r.front; } else static if (is(typeof(&(r.front())) == ElementType!R*)) { import std.algorithm.mutation : move; return move(r.front); } else { static assert(0, "Cannot move front of a range with a postblit and an rvalue front."); } } Ali |
Copyright © 1999-2021 by the D Language Foundation