digitalmars.D.learn - Trying to understand map being a template
- =?UTF-8?B?Tm/DqQ==?= Falzon (44/44) Jan 05 2024 On the subject of `map` taking the function as template
- H. S. Teoh (11/25) Jan 05 2024 That's simple, if the argument is a runtime function, it is treated as a
- Paul Backus (18/29) Jan 06 2024 It works for the same reason this example works:
- FeepingCreature (52/83) Jan 06 2024 To clarify, what this actually compiles to is:
- =?UTF-8?B?Tm/DqQ==?= Falzon (3/3) Jan 09 2024 Thank you very much for your answers. The point I had mostly
On the subject of `map` taking the function as template
parameter, I was surprised to see it could still be used with
functions determined at runtime, even closures, etc. I am trying
to understand the mechanism behind it.
The commented out line causes the error that `choice(funcs)`
cannot be determined at compile time, which is fair, but how is
it not the same case for `func` two lines above? I thought it
might be because the functions are literals visible at compile
time, but the closure makes that dubious.
```
import std.stdio;
import std.algorithm;
import std.random;
void main()
{
int r = uniform(0,100);
int delegate(int)[] funcs = [
x => x * 2,
x => x * x,
x => 3,
x => x * r // Closure
];
auto foo = [1,2,3,4,5];
foreach(i; 0..10)
{
// This is fine:
auto func = funcs.choice;
writeln(foo.map!func);
// This is not?
// writeln(foo.map!(funcs.choice));
}
}
```
In fact, how can the template be instantiated at all in the
following example, where no functions can possibly be known at
compile time:
```
auto do_random_map(int delegate(int)[] funcs, int[] values)
{
auto func = funcs.choice;
return values.map!func;
}
```
Thank you for the insights!
Jan 05 2024
On Fri, Jan 05, 2024 at 08:41:53PM +0000, Noé Falzon via Digitalmars-d-learn wrote:On the subject of `map` taking the function as template parameter, I was surprised to see it could still be used with functions determined at runtime, even closures, etc. I am trying to understand the mechanism behind it.That's simple, if the argument is a runtime function, it is treated as a function pointer (or delegate). [...]In fact, how can the template be instantiated at all in the following example, where no functions can possibly be known at compile time: ``` auto do_random_map(int delegate(int)[] funcs, int[] values) { auto func = funcs.choice; return values.map!func; } ```[...] The argument is taken to be a delegate to be bound at runtime. In the instantiation a shim is inserted to pass along the delegate from the caller's context. T -- Creativity is not an excuse for sloppiness.
Jan 05 2024
On Friday, 5 January 2024 at 20:41:53 UTC, Noé Falzon wrote:
In fact, how can the template be instantiated at all in the
following example, where no functions can possibly be known at
compile time:
```
auto do_random_map(int delegate(int)[] funcs, int[] values)
{
auto func = funcs.choice;
return values.map!func;
}
```
Thank you for the insights!
It works for the same reason this example works:
```d
void printVar(alias var)()
{
import std.stdio;
writeln(__traits(identifier, var), " = ", var);
}
void main()
{
int x = 123;
int y = 456;
printVar!x; // x = 123
printVar!y; // y = 456
x = 789;
printVar!x; // x = 789
}
```
Jan 06 2024
On Saturday, 6 January 2024 at 17:57:06 UTC, Paul Backus wrote:On Friday, 5 January 2024 at 20:41:53 UTC, Noé Falzon wrote:To clarify, what this actually compiles to is: ```d void main() { int x = 123; int y = 456; void printVar_x() { import std.stdio; writeln(__traits(identifier, x), " = ", x); } void printVar_y() { import std.stdio; writeln(__traits(identifier, y), " = ", y); } printVar_x; printVar_y; x = 789; printVar_x; } ``` Which lowers to: ```d struct mainStackframe { int x; int y; } void printVar_main_x(mainStackframe* context) { import std.stdio; writeln(__traits(identifier, context.x), " = ", context.x); } void printVar_main_y(mainStackframe* context) { import std.stdio; writeln(__traits(identifier, context.y), " = ", context.y); } void main() { // this is the only "actual" variable in main() mainStackframe frame; frame.x = 123; frame.y = 456; printVar_main_x(&frame); printVar_main_y(&frame); frame.x = 789; printVar_main_x(&frame); } Same with `map`.In fact, how can the template be instantiated at all in the following example, where no functions can possibly be known at compile time: ``` auto do_random_map(int delegate(int)[] funcs, int[] values) { auto func = funcs.choice; return values.map!func; } ``` Thank you for the insights!It works for the same reason this example works: ```d void printVar(alias var)() { import std.stdio; writeln(__traits(identifier, var), " = ", var); } void main() { int x = 123; int y = 456; printVar!x; // x = 123 printVar!y; // y = 456 x = 789; printVar!x; // x = 789 } ```
Jan 06 2024
Thank you very much for your answers. The point I had mostly misunderstood was alias template parameters, which make this possible.
Jan 09 2024









"H. S. Teoh" <hsteoh qfbox.info> 