Jump to page: 1 2 3
Thread overview
Casting MapResult
Jun 15, 2015
jmh530
Jun 15, 2015
ketmar
Jun 15, 2015
Justin Whear
Jun 15, 2015
Adam D. Ruppe
Jun 15, 2015
Ali Çehreli
Jun 15, 2015
Marc Schütz
Jun 15, 2015
Ali Çehreli
Jun 15, 2015
anonymous
Jun 15, 2015
jmh530
Jun 15, 2015
jmh530
Jun 15, 2015
ketmar
Jun 15, 2015
wobbles
Jun 15, 2015
Baz
Jun 15, 2015
jmh530
Jun 15, 2015
Baz
Jun 15, 2015
Baz
Jun 15, 2015
jmh530
Jun 15, 2015
jmh530
Jun 15, 2015
Baz
Jun 16, 2015
jmh530
Jun 16, 2015
John Colvin
Jun 16, 2015
jmh530
Jun 16, 2015
John Colvin
Jun 23, 2015
jmh530
Jun 23, 2015
John Colvin
Jun 23, 2015
jmh530
Jun 16, 2015
John Colvin
Jun 16, 2015
jmh530
Jun 16, 2015
jmh530
Jun 15, 2015
Ali Çehreli
June 15, 2015
I wrote a simple function to apply map to a float dynamic array

auto exp(float[] x) {
	auto y = x.map!(a => exp(a));
	return y;
}

However, the type of the result is MapResult!(__lambda2, float[]). It seems like some of the things that I might do to a float[], I can't do to this type, like adding them together. So I tried to adjust this by adding in a cast to float[], as in

float[] exp(float[] x) {
	auto y = x.map!(a => exp(a));
	cast(float[]) y;
	return y;
}

But I get an error that I can't convert MapResult!(__lambda2, float[]) to float[].

So I suppose I have two questions: 1) am I screwing up the cast, or is there no way to convert the MapResult to float[], 2) should I just not bother with map (I wrote an alternate, longer, version that doesn't use map but returns float[] properly).
June 15, 2015
On Mon, 15 Jun 2015 15:10:20 +0000, jmh530 wrote:

you shouldn't cast it like that. use `std.array.array` to get the actual array. like this:

  import std.array;

  auto y = x.map!(a => exp(a)).array;

the thing is that `map` returns so-called "lazy range". lazy ranges trying to not do any work until they are explicitely asked. i.e.

  y = x.map!(a => exp(a))

doesn't do any real processing yet, it only prepares everything for it. and only when you're calling `y.front`, `map` is processing one element. only one, as it has no need to process next until you call `popFront`.

tl;dr: you can't simply cast that lazy range back to array, you have to use `std.std.array` to get the array from it.

June 15, 2015
On Mon, 15 Jun 2015 15:10:20 +0000, jmh530 wrote:

> So I suppose I have two questions: 1) am I screwing up the cast, or is there no way to convert the MapResult to float[], 2) should I just not bother with map (I wrote an alternate, longer, version that doesn't use map but returns float[] properly).

MapResult is a wrapper around your original range that performs the mapping operation lazily.  If you want eagerly evaluate and get back to an array use the std.array.array function:

import std.array : array;
auto y = x.map!(a => exp(a)).array;

Or if you have already allocated an array of the appropriate size you can use std.algorithm.copy:

import std.algorithm : copy;
float[] y = new float[](appropriate_length);
x.map!(a => exp(a)).copy(y);
June 15, 2015
On Monday, 15 June 2015 at 15:10:24 UTC, jmh530 wrote:
> So I suppose I have two questions: 1) am I screwing up the cast, or is there no way to convert the MapResult to float[]

Don't cast it, just slap a .array on the end after importing std.range. Like so:

import std.algorithm;
import std.range; // add this line somewhere
float[] exp2(float[] x) {
        auto y = x.map!(a => exp(a));
        return y.array; // this line changed to make the array
}


The reason is that map returns a lazy generator instead of an array directly. It only evaluates on demand.

To get it to evaluate and save into an array, the .array function is called.

Tip though: don't call .array if you don't have to, chaining calls to map and such, even foreach(item; some_map_result) can be done without actually building the array and can give more efficiency.
June 15, 2015
On Monday, 15 June 2015 at 15:10:24 UTC, jmh530 wrote:
> float[] exp(float[] x) {
> 	auto y = x.map!(a => exp(a));
> 	cast(float[]) y;
> 	return y;
> }
>
> But I get an error that I can't convert MapResult!(__lambda2, float[]) to float[].
>
> So I suppose I have two questions: 1) am I screwing up the cast, or is there no way to convert the MapResult to float[], 2) should I just not bother with map (I wrote an alternate, longer, version that doesn't use map but returns float[] properly).

First off: Don't cast unless you know exactly what you're doing. It's easy to stumble into undefined behaviour land with casts.

To answer the question: You can convert from from MapResult to float[], but not with a cast. Instead, use std.array.array:
    import std.array: array;
    return x.map!(std.math.exp).array;
June 15, 2015
On Monday, 15 June 2015 at 15:10:24 UTC, jmh530 wrote:
> <snip>
> float[] exp(float[] x) {
> 	auto y = x.map!(a => exp(a));
> 	cast(float[]) y;
> 	return y;
> }
>


Also, I dont think your functions will work?
Your recursively calling "exp" in your map, but with a 'float' instead of 'float[]'.
June 15, 2015
Thank you all for the very fast answers. It looks like that works.
June 15, 2015
On 06/15/2015 08:21 AM, Adam D. Ruppe wrote:

> don't call .array if you don't have to, chaining calls to
> map and such, even foreach(item; some_map_result) can be done without
> actually building the array and can give more efficiency.

To add, the OP can use 'sum' or 'reduce' for "adding them together":

  http://dlang.org/phobos/std_algorithm_iteration.html

import std.stdio;
import std.algorithm;
import std.math;

void main()
{
    float[] arr = [ 1.5, 2.5 ];
    auto y = arr.map!exp;
    writeln(y.sum);    // same as sum(y)
}

An equivalent of the last line:

    writeln(reduce!((result, a) => result + a)(y));

Ali

June 15, 2015
On Monday, 15 June 2015 at 16:16:00 UTC, Ali Çehreli wrote:
> On 06/15/2015 08:21 AM, Adam D. Ruppe wrote:
>
> > don't call .array if you don't have to, chaining calls to
> > map and such, even foreach(item; some_map_result) can be done
> without
> > actually building the array and can give more efficiency.
>
> To add, the OP can use 'sum' or 'reduce' for "adding them together":
>
>   http://dlang.org/phobos/std_algorithm_iteration.html
>
> import std.stdio;
> import std.algorithm;
> import std.math;
>
> void main()
> {
>     float[] arr = [ 1.5, 2.5 ];
>     auto y = arr.map!exp;
>     writeln(y.sum);    // same as sum(y)
> }
>
> An equivalent of the last line:
>
>     writeln(reduce!((result, a) => result + a)(y));
>
> Ali

`sum` is better for floating-point ranges, because it uses pair-wise or Kahan summation if possible, in order to preserve precision.
June 15, 2015
On 06/15/2015 09:39 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm@gmx.net>" wrote:

>>     writeln(y.sum);    // same as sum(y)
>> }
>>
>> An equivalent of the last line:
>>
>>     writeln(reduce!((result, a) => result + a)(y));

> `sum` is better for floating-point ranges, because it uses pair-wise or
> Kahan summation if possible, in order to preserve precision.

Good point. I had mentioned that elsewhere after learning about it recently: "the sum of the elements of a range should be calculated by std.algorithm.sum, which uses special algorithms to achieve more accurate calculations for floating point types." :)

  http://ddili.org/ders/d.en/fibers.html#ix_fibers.recursion

Ali

« First   ‹ Prev
1 2 3