digitalmars.D.learn - how to return map(fn)
- steve (18/18) Feb 21 2022 following this example in the documentation of map:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (16/18) Feb 21 2022 What map and other Phobos algorithms return are called Voldemort types
- steve (12/14) Feb 22 2022 thanks for your help. I'm unfortunately still a bit confused.
- Steven Schveighoffer (21/35) Feb 22 2022 `map` does not eagerly allocate or process data. `map` is
- =?UTF-8?Q?Ali_=c3=87ehreli?= (14/16) Feb 22 2022 I think an eponymous template that defines an alias as in your original
- steve (24/24) Feb 23 2022 Thank you both a lot for your help. I am new to D so all of this
- Steven Schveighoffer (23/49) Feb 23 2022 I'm not sure what programming languages you are used to, so let
- steve (1/20) Feb 24 2022 that is exactly what I was trying to achieve thank you so much!
following this example in the documentation of map: ``` import std.algorithm.comparison : equal; import std.conv : to; alias stringize = map!(to!string); assert(equal(stringize([ 1, 2, 3, 4 ]), [ "1", "2", "3", "4" ])); ``` I would like to write a function that takes as its parameter a function and returns something like the alias in the example. i.e. something like: ``` float[] function(float[]) get_map(alias f){ return map!(f) } ``` I had a look at the source code for map but it seems to return a private struct, which doesn't help. Is there any way to get this to work?
Feb 21 2022
On 2/21/22 12:44, steve wrote:I had a look at the source code for map but it seems to return a private struct, which doesn't help.What map and other Phobos algorithms return are called Voldemort types for the reason you state: They are unmentionable. The usual way is to return 'auto' and the template system will take care of the rest: auto mapped(alias f, Range) (Range range) { import std.algorithm : map; return range.map!f(); } void main() { auto r = [1, 2].mapped!(i => 10 * i); import std.algorithm; assert(r.equal([10, 20])); } And I am sure your function is more capable than being the equivalent as map. ;) Ali
Feb 21 2022
On Monday, 21 February 2022 at 23:07:44 UTC, Ali Çehreli wrote:On 2/21/22 12:44, steve wrote: ...thanks for your help. I'm unfortunately still a bit confused. Maybe I wasn't clear or maybe I'm just missing something here. What I was trying to return is function that can then be applied to e.g. an array. As I understand the mapped function you wrote expects a range and a function argument something that would let me do ``` float my_function(float x){ return 2*x;} auto my_function_mapped = mapped(my_function); assert(my_function_mapped([1.,2.,3.]) == [2.,4.,6.]); ```
Feb 22 2022
On Tuesday, 22 February 2022 at 13:53:34 UTC, steve wrote:On Monday, 21 February 2022 at 23:07:44 UTC, Ali Çehreli wrote:`map` does not eagerly allocate or process data. `map` is actually a lazy function, meaning it doesn't actually run until you look at the elements. If you want a *concrete* range, you can use `array` from `std.array` as follows: ```d float[] get_map(alias f)(float[] input){ import std.algorithm : map; import std.array : array; return input.map!(f).array; } ``` `array` iterates all elements in the range and allocates a new array to hold the data. I know in other languages, people are used to just using arrays for all high-level composition, but D tries not to incur the allocation/copy penalty if it can help it. So it's worth questioning if you actually need an array, or if you can just use the map result directly. -SteveOn 2/21/22 12:44, steve wrote: ...thanks for your help. I'm unfortunately still a bit confused. Maybe I wasn't clear or maybe I'm just missing something here. What I was trying to return is function that can then be applied to e.g. an array. As I understand the mapped function you wrote expects a range and a function argument something that would let me do ```d float my_function(float x){ return 2*x;} auto my_function_mapped = mapped(my_function); assert(my_function_mapped([1.,2.,3.]) == [2.,4.,6.]); ```
Feb 22 2022
On 2/22/22 05:53, steve wrote:What I was trying to return is function that can then be applied to e.g. an array.I think an eponymous template that defines an alias as in your original post can be used as well: template mappified(alias func) { import std.algorithm : map; alias mappified = map!func; } void main() { import std.stdio; writeln([1,2].mappified!(a => a * 10)); } There is std.functional which includes function composition tools: https://dlang.org/phobos/std_functional.html Ali
Feb 22 2022
Thank you both a lot for your help. I am new to D so all of this is incredibly helpful. This seems like an amazing community! Ali I will have a look at std.functional as I think this is really what I was looking for. Until then, I have solved the problem with a simple class (e.g. below). I'm sure its not a particularly good way of doing it but it will work for now :). Also thank you for your book, its amazing! ``` class Mapper { float function(float) fn; this(float function(float) func) {this.fn = func;} float[] opCall(float[] x){ auto arr = new float[x.length]; foreach (i,elem; x) { arr[i] = fn(elem);} return arr; } } float times_two(float x) {return 2*x;} void main() { import std.stdio; Mapper map2x = new Mapper(×_two); writeln(map2x([1., 2., 3.])); }```
Feb 23 2022
On Wednesday, 23 February 2022 at 16:48:00 UTC, steve wrote:Thank you both a lot for your help. I am new to D so all of this is incredibly helpful. This seems like an amazing community! Ali I will have a look at std.functional as I think this is really what I was looking for. Until then, I have solved the problem with a simple class (e.g. below). I'm sure its not a particularly good way of doing it but it will work for now :). Also thank you for your book, its amazing! ```d class Mapper { float function(float) fn; this(float function(float) func) {this.fn = func;} float[] opCall(float[] x){ auto arr = new float[x.length]; foreach (i,elem; x) { arr[i] = fn(elem);} return arr; } } float times_two(float x) {return 2*x;} void main() { import std.stdio; Mapper map2x = new Mapper(×_two); writeln(map2x([1., 2., 3.])); } ```I'm not sure what programming languages you are used to, so let me just show you the idiomatic D way ;) ```d float times_two(float x) {return 2*x;} // if you would rather make sure the result is an array float[] times_two_array(float[] arr) { import std.algorithm; // for map import std.array; // for array return arr .map!times_two // map your function .array; // convert to an array } void main() { import std.stdio; import std.algorithm; // for map alias map2x = map!times_two; writeln(map2x([1., 2., 3.])); float[] arr2 = times_two_array([1., 2., 3.]); writeln(arr2); } ``` -Steve
Feb 23 2022
float times_two(float x) {return 2*x;} // if you would rather make sure the result is an array float[] times_two_array(float[] arr) { import std.algorithm; // for map import std.array; // for array return arr .map!times_two // map your function .array; // convert to an array } void main() { import std.stdio; import std.algorithm; // for map alias map2x = map!times_two; writeln(map2x([1., 2., 3.])); float[] arr2 = times_two_array([1., 2., 3.]); writeln(arr2); } ``` -Stevethat is exactly what I was trying to achieve thank you so much!
Feb 24 2022