Jump to page: 1 2
Thread overview
xvalue and std::move in D
Mar 06, 2014
Edwin van Leeuwen
Mar 06, 2014
Mike Parker
Mar 06, 2014
Edwin van Leeuwen
Mar 06, 2014
bearophile
Mar 06, 2014
Remo
Mar 06, 2014
Nicolas Sicard
Mar 06, 2014
Edwin van Leeuwen
Mar 06, 2014
Mike Parker
Mar 06, 2014
Mike Parker
Mar 06, 2014
Edwin van Leeuwen
Mar 06, 2014
Ali Çehreli
March 06, 2014
I am trying to learn D and (partly) replace my C++ projects with D. Lately in C++ I have become a fan of the type of functional programming discussed here:
http://blog.knatten.org/2012/11/02/efficient-pure-functional-programming-in-c-using-move-semantics/
and was wondering if something similar is possible in D.

Basically the idea is to define functions as follows:

std::vector<double> add_to_vector( double x, std::vector<double> &&v ) {
 v.push_back(x);
 return v;
}

and call it as follows:

std::vector<double> v;
v = add_to_vector( 1.2, std::move( v ) );

I know I could do the same by passing a reference value, but this makes it explicit that I am changing v, while being as efficient as passing a reference (since it just reuses the memory allocated to v instead of making a copy).

Is this possible in D? I had a look through many tutorials and some of the docs, but could not find out how to do it.

Any suggestions would be appreciated.
March 06, 2014
On 3/6/2014 8:21 PM, Edwin van Leeuwen wrote:

>
> and call it as follows:
>
> std::vector<double> v;
> v = add_to_vector( 1.2, std::move( v ) );
>
> I know I could do the same by passing a reference value, but this makes
> it explicit that I am changing v, while being as efficient as passing a
> reference (since it just reuses the memory allocated to v instead of
> making a copy).
>
> Is this possible in D? I had a look through many tutorials and some of
> the docs, but could not find out how to do it.
>
> Any suggestions would be appreciated.

See std.algorithm.move

http://dlang.org/phobos/std_algorithm.html#move
March 06, 2014
On Thursday, 6 March 2014 at 11:28:21 UTC, Mike Parker wrote:
>
> See std.algorithm.move
>

Thank you, can't believe I missed that. How do I specify that the function expects a temporary/xvalue (&&) parameter though?
March 06, 2014
Edwin van Leeuwen:

> Thank you, can't believe I missed that. How do I specify that the function expects a temporary/xvalue (&&) parameter though?

Thankfully D lacks the && operator.

Bye,
bearophile
March 06, 2014
On Thursday, 6 March 2014 at 12:01:25 UTC, bearophile wrote:
> Edwin van Leeuwen:
>
>> Thank you, can't believe I missed that. How do I specify that the function expects a temporary/xvalue (&&) parameter though?
>
> Thankfully D lacks the && operator.
>
> Bye,
> bearophile

But is also locks r-value references, and this is a problem.
March 06, 2014
On Thursday, 6 March 2014 at 11:49:51 UTC, Edwin van Leeuwen
wrote:
> On Thursday, 6 March 2014 at 11:28:21 UTC, Mike Parker wrote:
>>
>> See std.algorithm.move
>>
>
> Thank you, can't believe I missed that. How do I specify that the function expects a temporary/xvalue (&&) parameter though?

What are you trying to do? D is not C++11. Pure functional
programming in D follows a different path.
March 06, 2014
On 3/6/2014 8:49 PM, Edwin van Leeuwen wrote:
> On Thursday, 6 March 2014 at 11:28:21 UTC, Mike Parker wrote:
>>
>> See std.algorithm.move
>>
>
> Thank you, can't believe I missed that. How do I specify that the
> function expects a temporary/xvalue (&&) parameter though?

D doesn't have anything like that. The compiler will generally move for you when possible. Passing an RValue to a function will be done as a move. When returning structs from a function, they're moved. For LValues, it's up to the caller to make the move with std.algorithm.move. There's been a good deal of discussion here in the NG about this. Hit google with 'dlang move semantics' and you'll get some hits. There's also Ali's presentation (video[1] and slides[2]) from last year's DConf.

[1] http://www.youtube.com/watch?v=mPr2UspS0fE
[2] http://dconf.org/2013/talks/cehreli.pdf
March 06, 2014
On Thursday, 6 March 2014 at 12:08:35 UTC, Nicolas Sicard wrote:
> On Thursday, 6 March 2014 at 11:49:51 UTC, Edwin van Leeuwen
> wrote:
>> On Thursday, 6 March 2014 at 11:28:21 UTC, Mike Parker wrote:
>>>
>>> See std.algorithm.move
>>>
>>
>> Thank you, can't believe I missed that. How do I specify that the function expects a temporary/xvalue (&&) parameter though?
>
> What are you trying to do? D is not C++11. Pure functional
> programming in D follows a different path.

I guess what I am trying to do is allow code that looks like this:

v = add_to_vector( x, v );

while enforcing that v is never copied. I know there are other ways to do this, i.e.
void add_to_vector( x, ref v );

but for me the earlier pattern is more explicit about what is happening, while still being as efficient.

March 06, 2014
On Thursday, 6 March 2014 at 12:10:40 UTC, Mike Parker wrote:
> On 3/6/2014 8:49 PM, Edwin van Leeuwen wrote:
>> On Thursday, 6 March 2014 at 11:28:21 UTC, Mike Parker wrote:
>>>
>>> See std.algorithm.move
>>>
>>
>> Thank you, can't believe I missed that. How do I specify that the
>> function expects a temporary/xvalue (&&) parameter though?
>
> D doesn't have anything like that. The compiler will generally move for you when possible. Passing an RValue to a function will be done as a move. When returning structs from a function, they're moved. For LValues, it's up to the caller to make the move with std.algorithm.move. There's been a good deal of discussion here in the NG about this. Hit google with 'dlang move semantics' and you'll get some hits. There's also Ali's presentation (video[1] and slides[2]) from last year's DConf.
>
> [1] http://www.youtube.com/watch?v=mPr2UspS0fE
> [2] http://dconf.org/2013/talks/cehreli.pdf

Thank you for those links/pointers. I'll have a look at those.
March 06, 2014
On 3/6/2014 9:38 PM, Edwin van Leeuwen wrote:

> I guess what I am trying to do is allow code that looks like this:
>
> v = add_to_vector( x, v );
>
> while enforcing that v is never copied. I know there are other ways to
> do this, i.e.
> void add_to_vector( x, ref v );
>
> but for me the earlier pattern is more explicit about what is happening,
> while still being as efficient.
>

import std.stdio;

struct Foo {
    int x, y;
}

Foo add( Foo f, int val ) {
    writefln( "By val verision" );
    return Foo( f.x + val, f.y + val );
}

Foo add( ref Foo f, int val ) {
    writefln( "Ref version" );
    return Foo( f.x + val, f.y + val );
}

void main() {
    Foo f1 = Foo( 1, 2 );
    Foo f2 = add( f1, 1 ); // by ref version

    import std.algorithm : move;
    Foo f3 = add( f2.move, 4 ); // by val version, no copy

    // First is by ref, second is by val with no copy
    Foo f4 = f3.add( 2 ).add( 5 );
}
« First   ‹ Prev
1 2