www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Can I pass a function by parameter?

reply "AsmMan" <jckj33 gmail.com> writes:
I'm trying to use a bit of function programming.

In a function like this:

int f(in int[] arr, bool delegate(int) func);

call using:

bool g(int n) { ... }
f(arr, g);

instead of:

f(arr, x => x == 0);

it is possible?
Sep 07 2014
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Sunday, 7 September 2014 at 20:47:47 UTC, AsmMan wrote:
 I'm trying to use a bit of function programming.

 In a function like this:

 int f(in int[] arr, bool delegate(int) func);

 call using:

 bool g(int n) { ... }
 f(arr, g);

 instead of:

 f(arr, x => x == 0);

 it is possible?
bool g(int n) { ... } f(arr, &g); Also, these sort of questions are better in http://forum.dlang.org/group/digitalmars.D.learn
Sep 07 2014
next sibling parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Sunday, 7 September 2014 at 21:02:16 UTC, John Colvin wrote:
 bool g(int n) { ... }
 f(arr, &g);
This will fail if `&g` is a function pointer, such as when `g` is declared at module-level scope. In that case, it has to be explicitly converted to a delegate: --- import std.functional : toDelegate; int f(in int[] arr, bool delegate(int) func); bool g(int n) { ... } f(arr, toDelegate(&g)); --- Alternatively, make `f` receive a function pointer instead of a delegate: --- int f(in int[] arr, bool function(int) func); bool g(int n) { ... } f(arr, &g); ---
Sep 07 2014
parent reply "AsmMan" <jckj33 gmail.com> writes:
On Sunday, 7 September 2014 at 21:23:26 UTC, Jakob Ovrum wrote:
 On Sunday, 7 September 2014 at 21:02:16 UTC, John Colvin wrote:
 bool g(int n) { ... }
 f(arr, &g);
This will fail if `&g` is a function pointer, such as when `g` is declared at module-level scope. In that case, it has to be explicitly converted to a delegate: --- import std.functional : toDelegate; int f(in int[] arr, bool delegate(int) func); bool g(int n) { ... } f(arr, toDelegate(&g)); --- Alternatively, make `f` receive a function pointer instead of a delegate: --- int f(in int[] arr, bool function(int) func); bool g(int n) { ... } f(arr, &g); ---
Thank you too. Btw, why the & operator in this syntax? I used to think ref keyword sort of C's T** and & operator is neeeded.. or is it because f can be a function called without pass any parameter?
Sep 07 2014
parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Sunday, 7 September 2014 at 21:31:11 UTC, AsmMan wrote:
 Thank you too. Btw, why the & operator in this syntax? I used 
 to think ref keyword sort of C's T** and & operator is 
 neeeded.. or is it because f can be a function called without 
 pass any parameter?
In D, the address-of operator has to be used to get a function pointer or delegate from a function or member function. This is unlike C and C++, where the function is implicitly convertible to its function-pointer type. This difference in rules may be because D has functions that can be called without parentheses: --- int foo() { return 42; } // Note: `bar` is an overload set. void bar(void function() a) {} void bar(int a) {} void main() { assert(foo() == 42); // Nullary functions can also be called without parentheses. assert(foo == 42); bar(foo); // If function pointers worked like in C, which overload should be called? } ---
Sep 07 2014
next sibling parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Sunday, 7 September 2014 at 21:42:31 UTC, Jakob Ovrum wrote:
 void bar(void function() a) {}
s/void function() a/int function() a/
Sep 07 2014
prev sibling next sibling parent reply "AsmMan" <jckj33 gmail.com> writes:
On Sunday, 7 September 2014 at 21:42:31 UTC, Jakob Ovrum wrote:
 On Sunday, 7 September 2014 at 21:31:11 UTC, AsmMan wrote:
 Thank you too. Btw, why the & operator in this syntax? I used 
 to think ref keyword sort of C's T** and & operator is 
 neeeded.. or is it because f can be a function called without 
 pass any parameter?
In D, the address-of operator has to be used to get a function pointer or delegate from a function or member function. This is unlike C and C++, where the function is implicitly convertible to its function-pointer type. This difference in rules may be because D has functions that can be called without parentheses: --- int foo() { return 42; } // Note: `bar` is an overload set. void bar(void function() a) {} void bar(int a) {} void main() { assert(foo() == 42); // Nullary functions can also be called without parentheses. assert(foo == 42); bar(foo); // If function pointers worked like in C, which overload should be called? } ---
I got it. Why it doesn't works if foo is a method?
Sep 07 2014
parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Monday, 8 September 2014 at 03:01:40 UTC, AsmMan wrote:
 I got it. Why it doesn't works if foo is a method?
Taking the address of a method/member function yields a delegate, not a function pointer. Delegates are fat pointers; they contain a pointer to the function as well as a pointer to the context (the context is a hidden argument to the function, such as the this-reference of a class method). The context pointer is needed when calling the function, so they are encapsulated in one convenient type, which is the delegate type. Function pointers can be converted to delegates through a simple wrapper function (which is how std.functional.toDelegate achieves it), but delegates cannot be wrapped by a function pointer without introducing additional parameters to the function in order to pass the context pointer. Additionally, the *type* of the context pointer is erased, which is immensely handy as it means delegates with different contexts can be freely mixed, but it means there's no way to know the type of the context (such as a class type) just from the delegate, so there is no generic `toFunctionPointer` function that would roughly do the inverse of `toDelegate`. Each case has to be dealt with on a case-by-case basis. As function pointers can be converted to delegates, delegates are the more versatile of the two. I recommend using delegates unless there is a good reason not to.
Sep 07 2014
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Monday, 8 September 2014 at 05:04:21 UTC, Jakob Ovrum wrote:
 Function pointers can be converted to delegates through a 
 simple wrapper function (which is how std.functional.toDelegate 
 achieves it), but delegates cannot be wrapped by a function 
 pointer without introducing additional parameters to the 
 function in order to pass the context pointer.
Actually, this is possible using a trampoline.
Sep 07 2014
parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Monday, 8 September 2014 at 06:23:40 UTC, deadalnix wrote:
 On Monday, 8 September 2014 at 05:04:21 UTC, Jakob Ovrum wrote:
 Function pointers can be converted to delegates through a 
 simple wrapper function (which is how 
 std.functional.toDelegate achieves it), but delegates cannot 
 be wrapped by a function pointer without introducing 
 additional parameters to the function in order to pass the 
 context pointer.
Actually, this is possible using a trampoline.
True. AFAICT, a cross-platform, cross-architecture generic function for that is non-trivial and might be a neat candidate for Phobos.
Sep 07 2014
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Sunday, 7 September 2014 at 21:42:31 UTC, Jakob Ovrum wrote:
 On Sunday, 7 September 2014 at 21:31:11 UTC, AsmMan wrote:
 Thank you too. Btw, why the & operator in this syntax? I used 
 to think ref keyword sort of C's T** and & operator is 
 neeeded.. or is it because f can be a function called without 
 pass any parameter?
In D, the address-of operator has to be used to get a function pointer or delegate from a function or member function. This is unlike C and C++, where the function is implicitly convertible to its function-pointer type.
In fact the distinction is done by C and C++ only. Everything else, including every other language and the hardware they run on only understand what you call function pointer. What you call a function is simply an accident of history made many years ago in C when people had no idea what they were doing, and so we repeat it.
Sep 07 2014
parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Monday, 8 September 2014 at 03:37:45 UTC, deadalnix wrote:
 In fact the distinction is done by C and C++ only.
And by D.
Sep 07 2014
prev sibling parent "AsmMan" <jckj33 gmail.com> writes:
On Sunday, 7 September 2014 at 21:02:16 UTC, John Colvin wrote:
 On Sunday, 7 September 2014 at 20:47:47 UTC, AsmMan wrote:
 I'm trying to use a bit of function programming.

 In a function like this:

 int f(in int[] arr, bool delegate(int) func);

 call using:

 bool g(int n) { ... }
 f(arr, g);

 instead of:

 f(arr, x => x == 0);

 it is possible?
bool g(int n) { ... } f(arr, &g); Also, these sort of questions are better in http://forum.dlang.org/group/digitalmars.D.learn
Thanks. And sorry for wrong area. I'll post there next time. BTW, I'm answerning you after Jakob Ovrum because I opened two new tabs and send Jakob's one and had forget to send this...
Sep 07 2014
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Sunday, 7 September 2014 at 20:47:47 UTC, AsmMan wrote:
 I'm trying to use a bit of function programming.

 In a function like this:

 int f(in int[] arr, bool delegate(int) func);

 call using:

 bool g(int n) { ... }
 f(arr, g);

 instead of:

 f(arr, x => x == 0);

 it is possible?
In D there is a difference between a function and a first class function. Popular languages like C++ have a lot of accidental complexity, so we decided to introduce some to be successful as well.
Sep 07 2014