Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating curryable functions with lambdas in D doesn't work as class\struct memebers

Tags:

lambda

currying

d

I've been playing around with D, trying to mimic Scala style curryable functions by chaining lambda expressions.

I came up with this:

immutable foo=function(immutable int x)=>(immutable int y)=>(x+y);
struct S
{
    static immutable foo=function(immutable int x)=>(immutable int y)=>(x+y);
}
class C     static immutable foo=function(immutable int x)=>(immutable int y)=>(x+y);
}

void main()
{
    writefln("global\t%s",foo(1)(2));
    writefln("struct\t%s",S.foo(1)(2));
    writefln("class\t%s",C.foo(1)(2));
}

This is what I get when I run it:

global  3
struct  1528543170
Segmentation fault

As you can see, my method works well for the global function variable, but the struct's static function variable gives junk result, and the class's static function variable fails completely. If I remove the x from the return expression - function(immutable int x)=>(immutable int y)=>(y) - the struct version gives the correct result(2), but the class version still fails.

If I use a regular method, instead of a function variable:

immutable foo=function(immutable int x)=>(immutable int y)=>(x+y);
struct S
{
    static auto foo(immutable int x)
    {
        return (immutable int y)=>(x+y);
    }
}
class C
{
    static auto foo(immutable int x)
    {
        return (immutable int y)=>(x+y);
    }
}

void main()
{
    writefln("global\t%s",foo(1)(2));
    writefln("struct\t%s",S.foo(1)(2));
    writefln("class\t%s",C.foo(1)(2));
}

it works just fine:

global  3
struct  3
class   3

And I also get the advantage of using delegates(the compiler won't allow delegates in the first version) - but this style is less elegant.

I am well aware that D has the curry function in the std.functional library for currying functions, but sometimes it's more comfortable to make a function curryable by default, and beside - I'm curious to know why my first version doesn't work.

Any ideas?

UPDATE

OK, I've filed a bug. I've done some more digging, and it turns out the argument list of foo gets shifted, and that's why x gets junk data.

like image 662
Idan Arye Avatar asked Jun 11 '12 17:06

Idan Arye


People also ask

Can lambdas be templated?

Lambda-expressions are not allowed in unevaluated expressions, template arguments, alias declarations, typedef declarations, and anywhere in a function (or function template) declaration except the function body and the function's default arguments.

How do you pass lambda function in CPP?

Only variables that are mentioned in the lambda body are captured when a capture-default is used. To use lambda expressions in the body of a class member function, pass the this pointer to the capture clause to provide access to the member functions and data members of the enclosing class.

What are the two conditions required for using a lambda function in a stream?

In order to match a lambda to a single method interface, also called a "functional interface", several conditions need to be met: The functional interface has to have exactly one unimplemented method, and that method (naturally) has to be abstract.

How do you structure a lambda function?

Lambda functions can be divided into two parts: code inside the handler function and the code outside of it. Code outside the handler function only gets executed during the cold start, while the code inside the handler executes per each function call.


1 Answers

Honestly, it looks like you ran into a compiler bug. Please report it. Since the variables in the struct and class are static, their behavior should be identical to that of the module-level variable, and clearly, it's not.

like image 52
Jonathan M Davis Avatar answered Oct 19 '22 20:10

Jonathan M Davis