Jump to page: 1 2
Thread overview
std.range.interfaces : InputRange moveFront
Nov 30, 2017
Tony
Nov 30, 2017
Ali Çehreli
Nov 30, 2017
Tony
Nov 30, 2017
Tony
Nov 30, 2017
Tony
Nov 30, 2017
Ali Çehreli
Dec 01, 2017
Johan Engelen
Dec 01, 2017
Johan Engelen
Dec 01, 2017
Ali Çehreli
Dec 03, 2017
Johan Engelen
Dec 03, 2017
Johan Engelen
Dec 01, 2017
Ali Çehreli
November 30, 2017
What does the moveFront() method do in the InputRange interface?

std.range.interfaces : InputRange.moveFront()
November 29, 2017
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
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
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
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
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
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
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
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
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
« First   ‹ Prev
1 2