www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - xvalue and std::move in D

reply "Edwin van Leeuwen" <bla bla.bla> writes:
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.
Mar 06 2014
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
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
Mar 06 2014
parent reply "Edwin van Leeuwen" <bla bla.bla> writes:
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?
Mar 06 2014
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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
Mar 06 2014
parent "Remo" <remo4d gmail.com> writes:
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.
Mar 06 2014
prev sibling next sibling parent reply "Nicolas Sicard" <dransic gmail.com> writes:
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.
Mar 06 2014
parent reply "Edwin van Leeuwen" <bla bla.bla> writes:
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.
Mar 06 2014
parent Mike Parker <aldacron gmail.com> writes:
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 ); }
Mar 06 2014
prev sibling parent reply Mike Parker <aldacron gmail.com> writes:
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
Mar 06 2014
parent "Edwin van Leeuwen" <bla bla.bla> writes:
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.
Mar 06 2014
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/06/2014 03:21 AM, Edwin van Leeuwen wrote:

 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-u ing-move-semantics/ I haven't read that yet but I have always returned a vector from a function that produced it instead of adding to a reference parameter.
 and was wondering if something similar is possible in D.
Most of the time it is automatic and a non-issue for arrays.
 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;
 }
Actually, when the name of the function is add_to_vector() anyway, there is an obvious side-effect. So, I would not return the result in C++. However, when the name is like make_vector() then I always return the result. The alternatives have many hard questions to answer: void make_vector(vector<double> & v) { // Should I clear v first? // Should I simply start appending to v? // etc. } All of the efficiency of doing that goes out the window when one considers exception safety. Anyway... Too much off topic... :)
 Is this possible in D?
T[] append(T)(T[] arr, T value) { arr ~= value; return arr; } Done. :) Slices consist of two members that are cheap to copy: The number of elements and the pointer to the first element. It is already as efficient as move in C++. You should also read the following article: http://dlang.org/d-array-article.html Ali
Mar 06 2014