Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function and delegate literals in D

Reading TDPL about function and delegate literals (5.6.1)

auto f = (int i) {}; 
assert(is(f == function));

I've got an assertion failure. Is this assertion correct?

I tried the following:

int z = 5;
auto f = (int i) { return i < 5; };
auto d = (int i) { return i < z; };
assert(is(typeof(f) == typeof(d)));

Assertion is valid there. Actually f is a delegate, not a function even if it doesn't need a frame pointer to access local variables. Is this a bug?

Also, I do not understand how assert(is(f == function)); should work.

I tried assert(is(f == delegate)); but it was failed also. What's wrong?

I use DMD32 D Compiler v2.053

UPDATE

auto f = (int i) {};
assert(is(typeof(f) == delegate))

Works correct, although there is no reason to be a delegate

But

auto f = function (int i) {};
assert(is(typeof(f) == void function(int))); // correct
assert(is(typeof(f) == function));           // failed!!!!!

Miracle. It seems D2 is not ready for production use yet.

like image 317
Stas Avatar asked Jun 21 '11 20:06

Stas


2 Answers

"f" is a variable. The is expression compares types. This should work:

assert(is(typeof(f) == delegate));

If you want to create a function instead of a delegate, you can use the function literal syntax:

auto f = function (int i) { ... };
assert(is(typeof(f) == function));    // should be true

If the function literal syntax is not used, the literal is assumed to be delegate (Expressions, look under "Function Literals". This makes sense because D should not change the type based on the whether the body of the literal needs the stack frame (this would be super screwy). EDIT: TDPL does actually specify that the compiler will infer a function instead of a delegate if it can, regardless of the "function" keyword. This seems like a poor idea to me, so this might be something that has been dropped.

As to why the is(f == function) doesn't work, this looks like a regression.

like image 98
Justin W Avatar answered Oct 17 '22 22:10

Justin W


You might find isFunctionPointer and isDelegate helpful.

Update:

See this, taken from traits.d:

template isSomeFunction(/+@@@BUG4217@@@+/T...)
    if (/+@@@BUG4333@@@+/staticLength!(T) == 1)
{
    enum bool isSomeFunction = isSomeFunction_bug4333!(T).isSomeFunction;
}
private template isSomeFunction_bug4333(T...)
{
    /+@@@BUG4333@@@+/enum dummy__ = T.length;
    static if (is(typeof(& T[0]) U : U*) && is(U == function))
        // T is a function symbol.
        enum bool isSomeFunction = true;
    else static if (is(T[0] W) || is(typeof(T[0]) W))
            // T is an expression or a type.  Take the type of it and examine.
        static if (is(W F : F*) && is(F == function))
            enum bool isSomeFunction = true; // function pointer
        else enum bool isSomeFunction = is(W == function) || is(W == delegate);
    else enum bool isSomeFunction = false;
}

I think it might explain some things.

In other words:

void main()
{
    static if (is(typeof(&main) T : T*))  static assert( is(T == function));
    static if (is(typeof(&main) U))       static assert(!is(U == function));
}
like image 45
user541686 Avatar answered Oct 17 '22 22:10

user541686