Re: Trying to understand map being a template

2024-01-09 Thread Noé Falzon via Digitalmars-d-learn
Thank you very much for your answers. The point I had mostly 
misunderstood was alias template parameters, which make this 
possible.


Re: Trying to understand map being a template

2024-01-06 Thread FeepingCreature via Digitalmars-d-learn

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:
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
}
```


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();
  printVar_main_y();
  frame.x = 789;
  printVar_main_x();
}


Same with `map`.


Re: Trying to understand map being a template

2024-01-06 Thread Paul Backus via Digitalmars-d-learn

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
}
```


Re: Trying to understand map being a template

2024-01-05 Thread H. S. Teoh via Digitalmars-d-learn
On Fri, Jan 05, 2024 at 08:41:53PM +, 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.


Trying to understand map being a template

2024-01-05 Thread Noé Falzon via Digitalmars-d-learn
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!