www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Assigning map result, and in-place map

reply Bert van Leeuwen <bert e.co.za> writes:
I'm a D n00b, so excuse my question if it is silly. I've cursorily "followed" D
for a few years, but only now bought "The D Programming Language" (great book,
very nicely written!) and started to really play with it.

I've run into two questions which I have not been able to find the answers to
online.

1) I have an int array which I want to replace elements of with compile-time
string expression, e.g.

i=new int[100];
auto b=map!("(a==0)?42:a")(i);
writeln(b);

Cool, that works. But now I want to get at the resulting array. If I replace
"auto b" with:
int[] b = map ...
that does not work ("cannot implicitly convert expression (map(i)) of type
Map!(result,int[]) to int[]")... fine, but how do I get to the int[] ?

2) Related to above, I want to do something like map, but not return a new
array, I want to modify elements in-place in the array. How do I do that?
(without explicitly iterating with foreach etc.)
Sep 03 2010
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Bert van Leeuwen" <bert e.co.za> wrote in message 
news:i5qftb$2a25$1 digitalmars.com...
 I'm a D n00b, so excuse my question if it is silly. I've cursorily 
 "followed" D for a few years, but only now bought "The D Programming 
 Language" (great book, very nicely written!) and started to really play 
 with it.

Welcome! :)
 I've run into two questions which I have not been able to find the answers 
 to online.

 1) I have an int array which I want to replace elements of with 
 compile-time string expression, e.g.

 i=new int[100];
 auto b=map!("(a==0)?42:a")(i);
 writeln(b);

 Cool, that works. But now I want to get at the resulting array. If I 
 replace "auto b" with:
 int[] b = map ...
 that does not work ("cannot implicitly convert expression (map(i)) of type 
 Map!(result,int[]) to int[]")... fine, but how do I get to the int[] ?

Instead of returning an array, map returns a range that computes the values lazily (on-demand when they're needed, instead of always computing all of them right away). This is done for performance reasons. But you can get an array with the array() function from the "std.array" module: auto b = array( map!("(a==0)?42:a")(i) ); or auto b=map!("(a==0)?42:a")(i); auto ba = array(b); BTW, instead of: map!("(a==0)?42:a")(i) You can do: map!"(a==0)?42:a"(i) A nifty little bit of syntax sugar for when there's only one template parameter.
 2) Related to above, I want to do something like map, but not return a new 
 array, I want to modify elements in-place in the array. How do I do that? 
 (without explicitly iterating with foreach etc.)

I'll leave this one for someone else to answer, as I don't know whether or not something like this is already in phobos. If not, such a function can definitely be made, and maybe someone has already done so...?
Sep 03 2010
parent Bert van Leeuwen <bert e.co.za> writes:
Thanks!

Nick Sabalausky Wrote:

 "Bert van Leeuwen" <bert e.co.za> wrote in message 
 news:i5qftb$2a25$1 digitalmars.com...
 I'm a D n00b, so excuse my question if it is silly. I've cursorily 
 "followed" D for a few years, but only now bought "The D Programming 
 Language" (great book, very nicely written!) and started to really play 
 with it.

Welcome! :)
 I've run into two questions which I have not been able to find the answers 
 to online.

 1) I have an int array which I want to replace elements of with 
 compile-time string expression, e.g.

 i=new int[100];
 auto b=map!("(a==0)?42:a")(i);
 writeln(b);

 Cool, that works. But now I want to get at the resulting array. If I 
 replace "auto b" with:
 int[] b = map ...
 that does not work ("cannot implicitly convert expression (map(i)) of type 
 Map!(result,int[]) to int[]")... fine, but how do I get to the int[] ?

Instead of returning an array, map returns a range that computes the values lazily (on-demand when they're needed, instead of always computing all of them right away). This is done for performance reasons. But you can get an array with the array() function from the "std.array" module: auto b = array( map!("(a==0)?42:a")(i) ); or auto b=map!("(a==0)?42:a")(i); auto ba = array(b); BTW, instead of: map!("(a==0)?42:a")(i) You can do: map!"(a==0)?42:a"(i) A nifty little bit of syntax sugar for when there's only one template parameter.
 2) Related to above, I want to do something like map, but not return a new 
 array, I want to modify elements in-place in the array. How do I do that? 
 (without explicitly iterating with foreach etc.)

I'll leave this one for someone else to answer, as I don't know whether or not something like this is already in phobos. If not, such a function can definitely be made, and maybe someone has already done so...?

Sep 03 2010
prev sibling parent reply Pelle <pelle.mansson gmail.com> writes:
On 09/03/2010 11:42 AM, Bert van Leeuwen wrote:

 2) Related to above, I want to do something like map, but not return a new
array, I want to modify elements in-place in the array. How do I do that?
(without explicitly iterating with foreach etc.)

I don't know if this is intended to be supported, but at least for now this works: int[] xs = [1,2,3,4,5,6,7]; copy(map!`a*a`(xs), xs); writeln(xs); [1, 4, 9, 16, 25, 36, 49]
Sep 03 2010
next sibling parent reply Bert van Leeuwen <bert e.co.za> writes:
Pelle Wrote:

 On 09/03/2010 11:42 AM, Bert van Leeuwen wrote:
 
 2) Related to above, I want to do something like map, but not return a new
array, I want to modify elements in-place in the array. How do I do that?
(without explicitly iterating with foreach etc.)

I don't know if this is intended to be supported, but at least for now this works: int[] xs = [1,2,3,4,5,6,7]; copy(map!`a*a`(xs), xs); writeln(xs); [1, 4, 9, 16, 25, 36, 49]

Interesting. For large arrays, that seems to take almost double the time of creating a new one with array() (as in Nick's reply). So copy() obviously doesn't do it in place (not surprising given its name), and presumably makes a temporary array first from which to copy to a.
Sep 03 2010
parent reply Pelle <pelle.mansson gmail.com> writes:
On 09/03/2010 12:32 PM, Bert van Leeuwen wrote:
 Pelle Wrote:

 On 09/03/2010 11:42 AM, Bert van Leeuwen wrote:

 2) Related to above, I want to do something like map, but not return a new
array, I want to modify elements in-place in the array. How do I do that?
(without explicitly iterating with foreach etc.)

I don't know if this is intended to be supported, but at least for now this works: int[] xs = [1,2,3,4,5,6,7]; copy(map!`a*a`(xs), xs); writeln(xs); [1, 4, 9, 16, 25, 36, 49]

Interesting. For large arrays, that seems to take almost double the time of creating a new one with array() (as in Nick's reply). So copy() obviously doesn't do it in place (not surprising given its name), and presumably makes a temporary array first from which to copy to a.

Try it again with -inline. For me it's within 10% with inline, and gains even more if you add -O and -release. It also doesn't allocate, which is just a bonus. :-)
Sep 03 2010
parent Bert van Leeuwen <bert e.co.za> writes:
Pelle Wrote:

 On 09/03/2010 12:32 PM, Bert van Leeuwen wrote:
 Pelle Wrote:

 On 09/03/2010 11:42 AM, Bert van Leeuwen wrote:

 2) Related to above, I want to do something like map, but not return a new
array, I want to modify elements in-place in the array. How do I do that?
(without explicitly iterating with foreach etc.)

I don't know if this is intended to be supported, but at least for now this works: int[] xs = [1,2,3,4,5,6,7]; copy(map!`a*a`(xs), xs); writeln(xs); [1, 4, 9, 16, 25, 36, 49]

Interesting. For large arrays, that seems to take almost double the time of creating a new one with array() (as in Nick's reply). So copy() obviously doesn't do it in place (not surprising given its name), and presumably makes a temporary array first from which to copy to a.

Try it again with -inline. For me it's within 10% with inline, and gains even more if you add -O and -release. It also doesn't allocate, which is just a bonus. :-)

Awesome, that made it run about 4x faster :) thanks!
Sep 03 2010
prev sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Fri, 03 Sep 2010 14:32:47 +0400, Bert van Leeuwen <bert e.co.za> wrote:

 Pelle Wrote:

 On 09/03/2010 11:42 AM, Bert van Leeuwen wrote:

 2) Related to above, I want to do something like map, but not return  

do that? (without explicitly iterating with foreach etc.) I don't know if this is intended to be supported, but at least for now this works: int[] xs = [1,2,3,4,5,6,7]; copy(map!`a*a`(xs), xs); writeln(xs); [1, 4, 9, 16, 25, 36, 49]

Interesting. For large arrays, that seems to take almost double the time of creating a new one with array() (as in Nick's reply). So copy() obviously doesn't do it in place (not surprising given its name), and presumably makes a temporary array first from which to copy to a.

I don't think you are right. This is how copy is defined in std.algorithm[1]: Range2 copy(Range1, Range2)(Range1 source, Range2 target) if (isInputRange!Range1 && isOutputRange!(Range2, ElementType!Range1)) { for (; !source.empty; source.popFront()) { put(target, source.front); } return target; } [1] http://dsource.org/projects/phobos/browser/trunk/phobos/std/algorithm.d#L4054
Sep 03 2010