Thread overview
Differences between lambda function and regular functions in higher order functions
Feb 21, 2022
steve
Feb 21, 2022
partypooper
Feb 21, 2022
Stanislav Blinov
Feb 21, 2022
steve
February 21, 2022

I am trying to implement a simple map function. I found code to do this in another post but it only seems to work with lambda functions and I do not understand why. Any help would be greatly appreciated

import std.stdio;

T[] map_vals(T,S)(scope T function(S) f, S[] a){
    auto b = new T[a.length];
    foreach(i,x;a) b[i] = f(x);
    return b;
}


auto timestwo(float x) {
    return 2*x;
    }

void main(){
    float[] my_array = [1., 2., 3.];
    auto ff = (float x)=>2*x;

    // This works
    writeln(map_vals(ff, my_array));

    // this does not
    // writeln(map_vals(timestwo, my_array));
}
February 21, 2022

On Monday, 21 February 2022 at 10:04:16 UTC, steve wrote:

>

I am trying to implement a simple map function. I found code to do this in another post but it only seems to work with lambda functions and I do not understand why. Any help would be greatly appreciated

import std.stdio;

T[] map_vals(T,S)(scope T function(S) f, S[] a){
    auto b = new T[a.length];
    foreach(i,x;a) b[i] = f(x);
    return b;
}


auto timestwo(float x) {
    return 2*x;
    }

void main(){
    float[] my_array = [1., 2., 3.];
    auto ff = (float x)=>2*x;

    // This works
    writeln(map_vals(ff, my_array));

    // this does not
    // writeln(map_vals(timestwo, my_array));
}

I guess because your function parameter is actually a pointer to a function. ff is a pointer to anonymous function. timestwo is not. This should work

writeln(map_vals(&timestwo, my_array));
February 21, 2022

On Monday, 21 February 2022 at 10:04:16 UTC, steve wrote:

>

I am trying to implement a simple map function. I found code to do this in another post but it only seems to work with lambda functions and I do not understand why. Any help would be greatly appreciated

import std.stdio;

T[] map_vals(T,S)(scope T function(S) f, S[] a){
    auto b = new T[a.length];
    foreach(i,x;a) b[i] = f(x);
    return b;
}

As partypooper says, with that singature it'll only work if you pass function pointer (whereas a lambda converts to one). Alternatively (and how it is typically done in i.e. D's standard library), you can pass your callable as a compile-time argument. This also has an advantage of supporting UFCS, as shown in this example:

import std.stdio;

// original, needs a function pointer
T[] map_vals(T,S)(scope T function(S) f, S[] a){
    auto b = new T[a.length];
    foreach(i,x;a) b[i] = f(x);
    return b;
}

// Takes the callable as a compile-time argument
auto map_vals(alias f,S)(S[] a)
if (is(typeof(f(a[0]))))
{
    alias T = typeof(f(a[0]));
    auto b = new T[a.length];
    foreach (i, ref x; a) b[i] = f(x);
    return b;
}

auto timestwo(float x) {
    return 2*x;
}

void main(){
    float[] my_array = [1., 2., 3.];
    auto ff = (float x)=>2*x;

    // This works
    writeln(map_vals(ff, my_array));

    // this works with pointer to timestwo
    writeln(map_vals(&timestwo, my_array));

    // and this works by just passing the symbol name,
    // also note UFCS syntax:
    my_array.map_vals!timestwo.writeln;

    // as does this:
    my_array.map_vals!ff.writeln;

    // and this:
    my_array.map_vals!(x => 2*x).writeln;
}

Note that map already exists in Phobos (https://dlang.org/phobos/std_algorithm_iteration.html#map), and that one makes a lazy range and doesn't allocate.

February 21, 2022

thanks a lot both! Yes I'm aware that map exists already. This was didactic. I had tried to find out whether lambdas generate function pointers but also couldn't figure that one out :D