www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How does calling function pointers work?

reply helxi <brucewayneshit gmail.com> writes:
As far as I understand, calling a function pointer with an 
argument in D looks like:

     call(&fnptr, argTofn0, argTofn1, argTofn3);

This immediately struck me a very weak syntax to me so I decided 
to explore my concerns.
I made a function pointer that takes an indefinite number of 
arguments.

      1  import std.stdio;
      2
      3  int total(int[] numbers ...) {
      4      int result;
      5      for(ulong i = 0; i < numbers.length; result += 
numbers[i++]){}
      6      return result;
      7  }
      8
      9
     10  void main() {
     11      writeln(total(1000, 200, 30, 4)); // 1234
     12      writeln(&total, 1000, 200, 30, 4); // 
55CA386877AC1000200304
     13      writeln((&total, 1000, 200, 30), 4); // error lmao
     14  }

How do you guys make writeln distinguish between an arg meant for 
writeln from an arg meant for &total?
FYI
Line 12 was meant to print 1234.
Line 13 was meant to print 1234 too, but for a different reason.
Nov 12 2018
next sibling parent helxi <brucewayneshit gmail.com> writes:
On Monday, 12 November 2018 at 16:08:28 UTC, helxi wrote:
 Line 12 was meant to print 1234.
 Line 13 was meant to print 1234 too, but for a different reason.
Correction, it was meant to print 12304. My bad.
Nov 12 2018
prev sibling parent reply Rene Zwanenburg <renezwanenburg gmail.com> writes:
On Monday, 12 November 2018 at 16:08:28 UTC, helxi wrote:
 As far as I understand, calling a function pointer with an 
 argument in D looks like:

     call(&fnptr, argTofn0, argTofn1, argTofn3);
Idk where you got that syntax from, but there's no syntactic difference between calling normal functions and function pointers: https://run.dlang.io/is/I6u0rg
Nov 12 2018
parent reply helxi <brucewayneshit gmail.com> writes:
On Monday, 12 November 2018 at 16:25:13 UTC, Rene Zwanenburg 
wrote:
 Idk where you got that syntax from, but there's no syntactic 
 difference between calling normal functions and function 
 pointers:
import std.stdio; import std.concurrency; import core.thread; void worker(int firstNumber) { foreach (i; 0 .. 4) { Thread.sleep(500.msecs); writeln(firstNumber + i); } } void main() { foreach (i; 1 .. 3) { spawn(&worker, i * 10); } } Looks like worker needs an int and spawn(&worker, i * 10) seems to feed it's second arg to worker(?)
Nov 12 2018
next sibling parent Alex <sascha.orlov gmail.com> writes:
On Monday, 12 November 2018 at 16:29:24 UTC, helxi wrote:
 On Monday, 12 November 2018 at 16:25:13 UTC, Rene Zwanenburg 
 wrote:
 Idk where you got that syntax from, but there's no syntactic 
 difference between calling normal functions and function 
 pointers:
import std.stdio; import std.concurrency; import core.thread; void worker(int firstNumber) { foreach (i; 0 .. 4) { Thread.sleep(500.msecs); writeln(firstNumber + i); } } void main() { foreach (i; 1 .. 3) { spawn(&worker, i * 10); } } Looks like worker needs an int and spawn(&worker, i * 10) seems to feed it's second arg to worker(?)
Yes, seems so. Accordingly to https://dlang.org/library/std/concurrency/spawn.html However, there are more restrictions on input params in the notes section.
Nov 12 2018
prev sibling next sibling parent Mike Parker <aldacron gmail.com> writes:
On Monday, 12 November 2018 at 16:29:24 UTC, helxi wrote:

 Looks like worker needs an int and spawn(&worker, i * 10) seems 
 to feed it's second arg to worker(?)
spawn is a template that takes a function pointer and a variable number of parameters. Both the pointer and the parameters are passed on to an internal _spawn function. https://github.com/dlang/phobos/blob/master/std/concurrency.d#L446 _spawn is has the same template parameters as spawn. It has an internal function that actually makes the call to the function pointer (fn): void exec() { thisInfo.ident = spawnTid; thisInfo.owner = ownerTid; fn(args); } https://github.com/dlang/phobos/blob/master/std/concurrency.d#L538 A few lines down from there, a pointer to exec is passed to either scheduler.spawn or the Thread constructor. When it's ultimately called, your function will be called in turn. At any rate, the actual call to the function pointer is fn(args).
Nov 12 2018
prev sibling parent Rene Zwanenburg <renezwanenburg gmail.com> writes:
On Monday, 12 November 2018 at 16:29:24 UTC, helxi wrote:
 On Monday, 12 November 2018 at 16:25:13 UTC, Rene Zwanenburg 
 wrote:
 Idk where you got that syntax from, but there's no syntactic 
 difference between calling normal functions and function 
 pointers:
import std.stdio; import std.concurrency; import core.thread; void worker(int firstNumber) { foreach (i; 0 .. 4) { Thread.sleep(500.msecs); writeln(firstNumber + i); } } void main() { foreach (i; 1 .. 3) { spawn(&worker, i * 10); } } Looks like worker needs an int and spawn(&worker, i * 10) seems to feed it's second arg to worker(?)
That's right. spawn() is a function in the standard library that takes a function pointer, and all the arguments to pass to that function. It's a bit unusual in that regard: normally when using function pointers the arguments are provided by the code that receives the function pointer. Internally, spawn will call the function pointer just like I did in my example, but on another thread. Here's an example where a function pointer is passed around with the arguments provided by the callee: https://run.dlang.io/is/ArCN5t
Nov 12 2018