Re: staticMap but with two arguments

2023-02-09 Thread Ali Çehreli via Digitalmars-d-learn

On 2/9/23 12:45, John Chapman wrote:
> On Thursday, 9 February 2023 at 19:17:55 UTC, Ali Çehreli wrote:
>> I could not figure out eliminating the hard-coded 4. Can we introspect
>> the parameter list of a template like 'fun' in the example? If we
>> could, then we could get 4 that way.
>
> Thank you for this. I don't mind hard-coding the N argument.
> TemplateArgsOf needs an instantiated template but maybe ```enum N =
> count(fun.stringof, ',') + 1``` is good enough.

Hopefully but very fragile:

template t(int[] T = [ 1, 2 ]) {}

void main() {
import std.algorithm : count;
enum N = count(t.stringof, ',') + 1;
static assert(N == 1); // FAILS
}

Same thing with any other thing with comma in it e.g.

template t(T = anotherTemplate!(1, 2)) {}

Ali



Re: staticMap but with two arguments

2023-02-09 Thread John Chapman via Digitalmars-d-learn

On Thursday, 9 February 2023 at 19:17:55 UTC, Ali Çehreli wrote:
I could not figure out eliminating the hard-coded 4. Can we 
introspect the parameter list of a template like 'fun' in the 
example? If we could, then we could get 4 that way.


Thank you for this. I don't mind hard-coding the N argument. 
TemplateArgsOf needs an instantiated template but maybe ```enum N 
= count(fun.stringof, ',') + 1``` is good enough.


Re: staticMap but with two arguments

2023-02-09 Thread Ali Çehreli via Digitalmars-d-learn

On 2/8/23 12:04, John Chapman wrote:

> rather than write it manually for each N?

import std.meta : AliasSeq;

template pickArgs(size_t totalElements,
  size_t argsPerElement,
  size_t whichElement,
  args...) {
alias pickArgs = AliasSeq!();
static foreach (a; 0 .. argsPerElement) {
pickArgs = AliasSeq!(pickArgs, args[whichElement + a * 
totalElements]);

}
}

template staticMapN(size_t N, alias fun, args...)
{
static assert(N != 0, "N must be non-zero.");
static assert((args.length % N) == 0,
  "Mismatched number of arguments");

enum totalElements = args.length / N;

alias staticMapN = AliasSeq!();
static foreach (e; 0 .. totalElements) {
staticMapN = AliasSeq!(staticMapN,
   fun!(pickArgs!(totalElements, N, e, args)));
}
}

// An example struct with some template parameters
struct S(T, size_t length, size_t foo, size_t bar) {
}

// An example template that creates instantiations of the S template
template Instantiate(T, size_t length, size_t foo, size_t bar) {
alias Instantiate = S!(T, length, foo, bar);
}

// Compile-time argument sets for three instantiations of the S template
alias myTypes = AliasSeq!(int, double, long);
alias mySizes = AliasSeq!(1, 2, 3);
alias myFoos = AliasSeq!(42, 43, 44);
alias myBars = AliasSeq!(100, 200, 300);

// A test with those 4 sets of template arguments
alias result = staticMapN!(4, Instantiate, myTypes, mySizes, myFoos, 
myBars);

pragma(msg, result);

void main() {
}

I could not figure out eliminating the hard-coded 4. Can we introspect 
the parameter list of a template like 'fun' in the example? If we could, 
then we could get 4 that way.


Ali



Re: staticMap but with two arguments

2023-02-08 Thread John Chapman via Digitalmars-d-learn

On Monday, 6 February 2023 at 09:17:07 UTC, Ali Çehreli wrote:

I adapted staticMap's implementation to two sets of arguments:


So I've got this implementation, but wonder if I can generalise 
the arg splitting portion rather than write it manually for each 
N?


```d
template staticMapN(size_t N, alias fun, args...) if (args.length 
% N == 0) {

  alias staticMapN = AliasSeq!();
  static foreach (i; 0 .. args.length / N)
static if (N == 1)
  staticMapN = AliasSeq!(staticMapN, fun!(args));
else static if (N == 2)
  staticMapN = AliasSeq!(staticMapN, fun!(args[0 .. $ / 
N][i], args[$ / N .. ($ / N) * 2][i]));

else static if (N == 3)
  staticMapN = AliasSeq!(staticMapN, fun!(args[0 .. $ / 
N][i], args[$ / N .. ($ / N) * 2][i], args[($ / N) * 2 .. ($ / N) 
* 3][i]));

// etc
}
```


Re: staticMap but with two arguments

2023-02-06 Thread John Chapman via Digitalmars-d-learn

On Monday, 6 February 2023 at 09:17:07 UTC, Ali Çehreli wrote:

I adapted staticMap's implementation to two sets of arguments:


Thanks Ali, that's perfect. I thought of splitting the args in 
half a few hours later but hadn't got around to trying it.


Re: staticMap but with two arguments

2023-02-06 Thread Ali Çehreli via Digitalmars-d-learn

On 2/5/23 17:20, John Chapman wrote:

> staticMap's "fun" can only be
> instantiated with a single argument, while I need it to work with two.

I adapted staticMap's implementation to two sets of arguments:

import std.meta : AliasSeq;

// The first half of 'args' is the "first arguments" and
// the second half is the "second arguments".
//
// (This can be generalized to N sets of arguments.)
template staticMap2(alias fun, args...)
{
alias firsts = args[0 .. $ / 2];
alias seconds = args[$ / 2 .. $];

static assert(firsts.length == seconds.length,
  "Mismatched number of first and second arguments");

alias staticMap2 = AliasSeq!();
static foreach (i; 0 .. firsts.length) {
staticMap2 = AliasSeq!(staticMap2, fun!(firsts[i], seconds[i]));
}
}

// An example struct with two template parameters
struct S(T, size_t length) {
}

// An example template that creates instantiations of the S template
// (This can be generalized to instantiation of any template.)
template Instantiate(T, size_t length) {
alias Instantiate = S!(T, length);
}

// An example use
alias myTypes = AliasSeq!(int, double, long);
alias mySizes = AliasSeq!(1, 2, 3);
alias result = staticMap2!(Instantiate, myTypes, mySizes);

pragma(msg, result);

void main() {
}

Ali



staticMap but with two arguments

2023-02-05 Thread John Chapman via Digitalmars-d-learn
I have two AliasSeqs: one containing a function's parameters 
(SourceSeq), the other containing the types I want to convert 
said parameters to (TargetSeq). I'd use something like staticMap 
to call the conversion function with both a parameter from 
SourceSeq and a type from TargetSeq, and return an AliasSeq of 
converted values which will be forwarded to another function. 
staticMap's "fun" can only be instantiated with a single 
argument, while I need it to work with two.


E.g.:
```
template toTarget(alias source, Target) {
  static if (is(typeof(source) == int) && is(Target == string)) 
// for example, convert int to string

}

alias TargetSeq = Parameters!targetFunc;

auto wrapperFunc(A...)(A) {
  alias SourceSeq = __traits(parameters);
  return targetFunc(staticMap!(toTarget, SourceSeq)); // How 
would I call staticMap (or something similar) with SourceSeq 
*and* TargetSeq?

}
```

I could build the list of converted values manually but I wanted 
something smart (like staticMap) to do it inline. I thought 
ApplyLeft/Right could help but couldn't get my head around it.