Re: My template tuple code does not compile

2019-03-01 Thread Simen Kjærås via Digitalmars-d-learn
On Wednesday, 27 February 2019 at 22:45:03 UTC, Victor Porton 
wrote:

I rewrote it again:

https://github.com/vporton/struct-params-dlang/blob/f50f7e5919f90b1d06bf0cc08e3055548aad1797/source/struct_params.d

But it does not work :-( What is my error?

source/struct_params.d(43,60): Error: function expected before 
`()`, not `()` of type `()`
source/struct_params.d(44,43): Error: undefined identifier 
`fieldsWithDefaults`
source/struct_params.d(56,11): Error: template instance 
`struct_params.ProviderParamsCode!("S", int, "x", float, "y")` 
error instantiating
source/struct_params.d(82,5): Error: mixin 
`struct_params.__unittest_L81_C1.ProviderParams!("S", int, "x", 
float, "y")` error instantiating


You seem to have misunderstood how staticMap works. It operates 
on a compile-time list of values, and only takes a single set of 
parameters: staticMap!(fn, item0, item1, item...), not 
staticMap!fn(item0, item1, item...).


In addition, Types.length.iota will create a run-time range of 
values, not a compile-time AliasSeq of values. For this, you can 
use std.meta.aliasSeqOf: staticMap!(regularField, 
aliasSeqOf!(Types.length.iota)).


Next, join expects a range, not an AliasSeq. In other words, 
staticMap!(...).join('\n') will fail to compile - staticMap!(...) 
will need to be turned into a range of some sort. We can do this 
the same way we'd turn any list of values into a range - by 
putting brackets around it. Just like [1,2,3] is a valid array, 
so is [staticMap!(...)], supposing the elements have some common 
type.


But wait - there's more! You're using __traits(identifier, 
Types[i]). As pointed out in 
https://forum.dlang.org/post/smgsgycpgvtagfsdx...@forum.dlang.org, this will fail for built-in types, as they don't have an identifier. You can get their names, as well as the name of any other type with Types[i].stringof.


Lastly, you have not imported std.typecons, so your use of 
Nullable will fail.


So, that's the issues that cause it to not compile. There are 
issues also in the code that isn't instantiated, i.e. 
callFunctionWithParamsStruct and 
callMemberFunctionWithParamsStruct. Since these aren't used, they 
don't cause compile failure yet. The main issue here is exactly 
the same as above: a conflation of run-time and compile-time 
responsibilities, this time when using map.


Since map is a run-time function, it can't do compile-time things 
like __traits(getMember) - you'll need to use staticMap for that. 
However, there's a much easier solution:


auto callFunctionWithParamsStruct(alias f, S)(S s) {
return f(s.tupleof);
}

The same thing can be done for callMemberFunctionWithParamsStruct.

Now, I will note that no checking is done that parameter names 
and field names match, so void fun(int numberOfBeans, string 
nameOfCat) can easily be called with struct S { int 
temperatureOfPudding; string declarationOfIndependence; }, but I 
will assume that's because you haven't gotten around to it yet.


--
  Simen


Re: My template tuple code does not compile

2019-02-27 Thread Victor Porton via Digitalmars-d-learn

I rewrote it again:

https://github.com/vporton/struct-params-dlang/blob/f50f7e5919f90b1d06bf0cc08e3055548aad1797/source/struct_params.d

But it does not work :-( What is my error?

source/struct_params.d(43,60): Error: function expected before 
`()`, not `()` of type `()`
source/struct_params.d(44,43): Error: undefined identifier 
`fieldsWithDefaults`
source/struct_params.d(56,11): Error: template instance 
`struct_params.ProviderParamsCode!("S", int, "x", float, "y")` 
error instantiating
source/struct_params.d(82,5): Error: mixin 
`struct_params.__unittest_L81_C1.ProviderParams!("S", int, "x", 
float, "y")` error instantiating


Re: My template tuple code does not compile

2019-02-27 Thread Q. Schroll via Digitalmars-d-learn
On Wednesday, 27 February 2019 at 03:53:35 UTC, Victor Porton 
wrote:
After following your suggestion to rewrite it with Stride it 
does not work either. I assume the error is somehow related to 
allSatisfy!.


https://github.com/vporton/struct-params-dlang/blob/c1adc86672f46fd6b743903cc270dceef120a8fe/source/struct_params.d

Please help. It is important for both D community and world at 
large.


In

static assert(allSatisfy!(x => isType!x, Types) && ...

you use `allSatisfy` as if it took a lambda function or something 
like that. It does not. It takes a expects a template.


First things first: The spec¹ says that allSatisfy!(F, T) «tests 
whether all given items satisfy a template predicate, i.e. 
evaluates to F!(T[0]) && F!(T[1]) && ... && F!(T[$ - 1]).» Here, 
`F` is not a lambda, it's a template.


In your case, you can use `isTypeTuple!Types` from the library² 
to check what you intend to check. For the values, unfortunately 
there is no library function to check that they are all strings. 
A specific solution is to use a (static) template


enum bool isStringValue(alias x) = is(typeof(x) == string);

and feed it to `allSatisfy`:

allSatisfy!(isStringValue, Names)

¹ https://dlang.org/library/std/meta/all_satisfy.html
² https://dlang.org/phobos/std_traits.html#isTypeTuple




Re: My template tuple code does not compile

2019-02-27 Thread Simen Kjærås via Digitalmars-d-learn
On Wednesday, 27 February 2019 at 03:53:35 UTC, Victor Porton 
wrote:
After following your suggestion to rewrite it with Stride it 
does not work either. I assume the error is somehow related to 
allSatisfy!.


https://github.com/vporton/struct-params-dlang/blob/c1adc86672f46fd6b743903cc270dceef120a8fe/source/struct_params.d

Please help. It is important for both D community and world at 
large.


Your problem is exactly here:

allSatisfy!(x => is(typeof(x) == string), Names)

allSatisfy expects its first parameter to be a template, not a 
function. We can introduce a simple helper template:


template isA(T) {
enum isA(alias U) = is(typeof(T) == U);
}

Then simply replace the code above with allSatisfy!(isA!string, 
Names).


--
  Simen


Re: My template tuple code does not compile

2019-02-26 Thread Victor Porton via Digitalmars-d-learn
After following your suggestion to rewrite it with Stride it does 
not work either. I assume the error is somehow related to 
allSatisfy!.


https://github.com/vporton/struct-params-dlang/blob/c1adc86672f46fd6b743903cc270dceef120a8fe/source/struct_params.d

Please help. It is important for both D community and world at 
large.


Re: My template tuple code does not compile

2019-02-26 Thread Q. Schroll via Digitalmars-d-learn

On Tuesday, 26 February 2019 at 22:56:37 UTC, Victor Porton wrote:

On Tuesday, 26 February 2019 at 22:51:15 UTC, Q. Schroll wrote:
Grouping arguments could be done, but from my experience, it 
does not buy you anything; rather it makes it worse. Better 
just deal with heterogeneous stuff just like 
std.typecons.Tuple does.


After fixing the error you pointed me, it does not work too:

mixin ProviderParams!("S", ((int, "x"), (float, "y")));

Also: Can I nevertheless group arguments?


No, not the way you do. The module std.meta defines AliasSeq as 
follows:


alias AliasSeq(X...) = X;

It is literally equivalent to

template AliasSeq(X...)
{
alias AliasSeq = X; // "eponymous template member"
}

In

mixin ProviderParams!("S", ((int, "x"), (float, "y")));

the parenthesized stuff like (int, "x") is invalid in terms of 
formal grammar. You could use AliasSeq!(int, "x") if you really 
want to display grouping in your source code. Note however that 
this does not do anything. The sequence is being flattened by the 
compiler, i.e.


mixin ProviderParams!("S", AliasSeq!(AliasSeq!(int, "x"), 
AliasSeq!(float, "y")));


is exactly the same as

mixin ProviderParams!("S", int, "x", float, "y");

which I wrote in my answer.

When you don't use a eponymous template member, you can access 
them manually:


template Pack(X...)
{
alias Contents = X; // not "eponymous template member"
}

Using this, you can create what I call packs. For some template 
T, while T!(AliasSeq!(int, bool), AliasSeq!(float, string, long)) 
is the same as writing T!(int, bool), the T!(Pack!(int, bool), 
Pack!(float, string, long)) is different from T!(int, bool, 
float, string, long). In the AliasSeq template, the eponymous 
template member feature of D immediately expands the sequence.


If the template T is defined like this:

template T(Args...)
{ .. }

In the AliasSeq case, Args[0] is int, Args[1] is bool, Args[2] is 
float, ...
In the Pack case, Args[0] is Pack!(int, bool), Args[1] is 
Pack!(float, string, long), and Args[0].Contents[0] is int, 
Args[0].Contents[1] is bool, Args[1].Contents[0] is float ...


I've used Packs once to get the Cartesian product of an AliasSeq 
of Packs. It is a mess. I'd only use Packs when absolutely 
necessary; in your case, it does not seem so.


In your case, you seem to need some initial thing "S" and then 
pairs of things.


template you_name_it(Arg, args...)
if (args.length % 2 == 0) // ensures pairs
{
static foreach (i; args.length / 2)
{
// access the type by args[2*i]
// access the name (or whatever) by args[2*i+1]
}
}

You could get the sequence of types and the sequence of names 
using


alias Types = Stride!(2, args);
alias Names = Stride!(2, args[1 .. $]);


Re: My template tuple code does not compile

2019-02-26 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Feb 26, 2019 at 10:56:37PM +, Victor Porton via Digitalmars-d-learn 
wrote:
[...]
> After fixing the error you pointed me, it does not work too:
> 
> mixin ProviderParams!("S", ((int, "x"), (float, "y")));

Try this:

mixin ProviderParams!("S", int, "x", float, "y");


> Also: Can I nevertheless group arguments?

Template argument lists auto-expand, so even if you could group
arguments, they make no functional difference.  If you truly need to
distinguish between groups of arguments, you have to pack them into a
non-autoexpanding group, for example:

template Group(Args...) {
// Note: NOT eponymous.
alias contents = Args;
}

mixin ProviderParams!("S", Group!(int, "x"), Group!(float, "y"));

Keep in mind, however, that inside ProviderParams you will need to
explicitly access .contents. For example:

mixin template ProviderParams(Args...) {
static foreach (arg; Args[1 .. $]) {{
alias type = arg.contents[0];
alias name = arg.contents[1];
}}
}


T

-- 
Prosperity breeds contempt, and poverty breeds consent. -- Suck.com


Re: My template tuple code does not compile

2019-02-26 Thread Victor Porton via Digitalmars-d-learn

On Tuesday, 26 February 2019 at 22:51:15 UTC, Q. Schroll wrote:
On Tuesday, 26 February 2019 at 21:43:31 UTC, Victor Porton 
wrote:
Compilation of unittest at the bottom of this file fails with 
an error. What is my error?

...

You have the line

   ProviderParams("S", ((int, "x"), (float, "y")));

Why do you even expect it to compile?
First, ProviderParams is a mixin template, so you'd need to 
instantiate it with the ! operator. Then, the expressions (int, 
"x") and so on do not make sense in D. You could have 
compile-time tuples (using AliasSeq from std.meta) containing 
types and other compile-time known stuff, but it wouldn't help 
directly.

You'd use the mixin template like this:

   mixin ProviderParams!("S", int, "x", float, "y");
   ^-- necessary   ^-- necessary

Grouping arguments could be done, but from my experience, it 
does not buy you anything; rather it makes it worse. Better 
just deal with heterogeneous stuff just like std.typecons.Tuple 
does.


You should definitely comment your code. Explain what you 
intend to do. It helps people helping you.


After fixing the error you pointed me, it does not work too:

mixin ProviderParams!("S", ((int, "x"), (float, "y")));

Also: Can I nevertheless group arguments?


Re: My template tuple code does not compile

2019-02-26 Thread Q. Schroll via Digitalmars-d-learn

On Tuesday, 26 February 2019 at 21:43:31 UTC, Victor Porton wrote:
Compilation of unittest at the bottom of this file fails with 
an error. What is my error?


I cannot tell you, why exactly you get these error messages. I 
can explain you the probable cause of the errors. I have not 
tested anything of what I tell you, as it is very vague.


You have the line

   ProviderParams("S", ((int, "x"), (float, "y")));

Why do you even expect it to compile?
First, ProviderParams is a mixin template, so you'd need to 
instantiate it with the ! operator. Then, the expressions (int, 
"x") and so on do not make sense in D. You could have 
compile-time tuples (using AliasSeq from std.meta) containing 
types and other compile-time known stuff, but it wouldn't help 
directly.

You'd use the mixin template like this:

   mixin ProviderParams!("S", int, "x", float, "y");
   ^-- necessary   ^-- necessary

Grouping arguments could be done, but from my experience, it does 
not buy you anything; rather it makes it worse. Better just deal 
with heterogeneous stuff just like std.typecons.Tuple does.


You should definitely comment your code. Explain what you intend 
to do. It helps people helping you.


My template tuple code does not compile

2019-02-26 Thread Victor Porton via Digitalmars-d-learn
Compilation of unittest at the bottom of this file fails with an 
error. What is my error?


https://github.com/vporton/struct-params-dlang/blob/c32cfde60dbb03cb80a4a8aeb8185f5c86705790/source/struct_params.d

It is very important both for this useful little D project and my 
bigger research project. Please help.


source/struct_params.d(74,30): Error: found `,` when expecting 
`.` following int
source/struct_params.d(74,32): Error: found `"x"` when expecting 
identifier following `int`.
source/struct_params.d(74,44): Error: found `,` when expecting 
`.` following float
source/struct_params.d(74,46): Error: found `"y"` when expecting 
identifier following `float`.