delegates, functions, and literals confusion
Mike Parker
aldacron at gmail.com
Thu Jul 4 02:18:52 PDT 2013
On Thursday, 4 July 2013 at 06:43:12 UTC, CJS wrote:
>
> In my case I'm trying to figure out the best way to pass
> functions to other fundtions. So I wrote the following toy code
> to see what the compiler would do. I'm trying to understand why
> the compiler emitted errors on the code below (shown w/
> comments). Any insight/suggestions on better ways to pass
> functions around would also be appreciated.
First, to clarify some terminology.
This is a function that takes a delegate as a parameter.
> void f(int delegate(int) h){
> writefln("h(0)=%d", h(0));
> }
This is a function that takes a function *pointer*, not a
function, as a parameter.
> void g(int function (int) h){
> writefln("h(0)=%d", h(0));
> }
>
This one is an inner function.
> int foo(int a){ return a+6;}
And this is a function literal which, in essence, is a function
pointer.
> auto bah = function int(int b){ return b+7;};
In D, functions are not first class objects as they are in some
other languages, so you can't actually pass them around. But what
you can pass around is a pointer to a function. Try this.
void g(int function (int) h) {
writefln("h(0)=%d", h(0));
}
void gg( int i ) { return i + 6; }
void main() { g( &gg ); }
Here, I'm passing a function pointer to g, which is exactly what
it wants.
In your code, g(bah) succeeds because when the compiler
encounters a function literal, it creates a function somewhere
and stores a pointer where you assign it. So your bah is a
function pointer. Hence g(bah) succeeds. g(&bah) fails because
&bah makes it a pointer to a function pointer, which is not the
kind of parameter that g accepts.
Delegates and function pointers are quite similar in usage, but
architecturally different. A function pointer consists of one
thing, a pointer to a function. A delegate has a pointer to a
function *and* a reference to the stack frame from whence it
came. There are three ways to create a delegate: via a delegate
literal, via taking a pointer to a class method, or via taking a
pointer to an inner method. Consider this:
void main() {
int i = 10;
int foo( int a ) {
i = a + 6;
return i;
}
f( &foo );
writeln( i );
int j;
}
Because a delegate can reference the stackframe where it was
created, you can use them to modify variables inside a function
or to modify class member variables. Delegates declared inside a
function can only modify variables declared before the inner
function or delegate literal. So in my example above, foo can
modify i, but trying to modify j will be a compiler error.
So f(foo) fails because just 'foo' doesn't do anything. A
function can be called like foo(), or a pointer can be taken with
&foo, but just 'foo' is meaningless. f(&foo) succeeds because
taking a pointer to an inner function creates a delegate. f(bah)
fails because bah is a function pointer and not a delegate.
f(&bah) fails because &bah is a pointer to a function pointer.
You should now also understand why g(foo) and g(&foo) fail as
well.
>
> f(foo); //error
> f(&foo);
> f(bah); //error
> f(&bah); // error
>
> g(foo); //error
> g(&foo); //error
> g(bah);
> g(&bah); //error
>
> }
More information about the Digitalmars-d-learn
mailing list