Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
November 11, 2011 How to implement predicates for Filter!(Pred, Tuple) | ||||
---|---|---|---|---|
| ||||
I've written a Filter-Template, which implements the well-known function for template arguments:
-----
template Filter(alias SPred, E...)
{
static if(E.length == 0) {
alias TypeTuple!() Filter;
}
else
{
static if(SPred!(E[0]))
{
alias TypeTuple!(E[0], Filter!(SPred, E[1..$])) Filter;
}
else
{
alias Filter!(SPred, E[1..$]) Filter;
}
}
}
------
This works just fine:
---
template IsEqual(int This)
{
template IsEqual(int That)
{
enum bool IsEqual = This == That;
}
}
static assert(is(Filter!(IsEqual!5, 5,1,5,1,5) == TypeTuple!(5, 5, 5)));
---
However I can't use it directly, for example like this:
> pragma(msg, IsEqual!(5)!5);
However if I wouldn't rely on the ETT, and use a different name for the inner template, it will work.
---
template IsEqual(int This)
{
template Pred(int That)
{
enum bool Pred = This == That;
}
}
pragma(msg, IsEqual!(5).Pred!(5));
---
But that will make IsEqual less elegant to use in conjunction with filter.
So, is there a way to elegantly use one template in both cases? Otherwise I
would declare two versions:
one with a single and one with two parameter.
--
Tobias
|
November 11, 2011 Re: How to implement predicates for Filter!(Pred, Tuple) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | On 11/11/2011 11:04 AM, Tobias Pankrath wrote:
> I've written a Filter-Template, which implements the well-known function for
> template arguments:
>
> -----
> template Filter(alias SPred, E...)
> {
> static if(E.length == 0) {
> alias TypeTuple!() Filter;
> }
> else
> {
> static if(SPred!(E[0]))
> {
> alias TypeTuple!(E[0], Filter!(SPred, E[1..$])) Filter;
> }
> else
> {
> alias Filter!(SPred, E[1..$]) Filter;
> }
> }
> }
> ------
>
> This works just fine:
> ---
> template IsEqual(int This)
> {
> template IsEqual(int That)
> {
> enum bool IsEqual = This == That;
> }
> }
>
> static assert(is(Filter!(IsEqual!5, 5,1,5,1,5) == TypeTuple!(5, 5, 5)));
> ---
>
> However I can't use it directly, for example like this:
>> pragma(msg, IsEqual!(5)!5);
>
> However if I wouldn't rely on the ETT, and use a different name for the
> inner
> template, it will work.
>
> ---
> template IsEqual(int This)
> {
> template Pred(int That)
> {
> enum bool Pred = This == That;
> }
> }
>
> pragma(msg, IsEqual!(5).Pred!(5));
> ---
>
> But that will make IsEqual less elegant to use in conjunction with filter.
> So, is there a way to elegantly use one template in both cases? Otherwise I
> would declare two versions:
> one with a single and one with two parameter.
>
> --
> Tobias
>
This is a sketch of how I would approach your problem. The "Curry" template automatically creates the nested template version from an unnested one. You are then allowed to use both IsEqual!(val) and IsEqual!(val1, val2).
template IsEqual(int This, int That){
enum IsEqual = This == That;;
}
mixin(Curry!IsEqual);
static assert(IsEqual!(1,1));
static assert(!IsEqual!(1,2));
alias IsEqual!(1) IsEqual1;
static assert(IsEqual1!1);
static assert(!IsEqual1!2);
// implementation of Curry:
import std.array, std.string;
template Curry(alias x){
enum Curry = curryImpl(x.stringof);
}
private string curryImpl(string decl){
auto psta = decl.indexOf("(");
auto name = decl[0..psta];
auto pstr = decl[psta+1..$-1];
auto prms = pstr.split(",");
string r;
foreach(prm; prms) r ~= "template " ~ name ~ "("~prm~"){";
r ~= "enum " ~ name ~ " = ." ~ name ~ "!("; // TODO: make this work for templates not at module scope
foreach(prm; prms) r ~= prm[prm.indexOf(" ")+1..$]~",";
r ~= ");";
foreach(prm; prms) r~="}";
return r;
}
|
November 11, 2011 Re: How to implement predicates for Filter!(Pred, Tuple) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On 11/11/11 6:20 PM, Timon Gehr wrote: > This is a sketch of how I would approach your problem. The "Curry" > template automatically creates the nested template version from an > unnested one. You are then allowed to use both IsEqual!(val) and > IsEqual!(val1, val2). > […] See also: https://gist.github.com/1191885#L27 Reminds me that I really have to put together a std.meta proposal – if I would only find time to do so… David |
November 11, 2011 Re: How to implement predicates for Filter!(Pred, Tuple) | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | To be more precise, Tobias, my PApply!() would allow you to define your predicate »unnested«, i.e. just as a template with two parameters and then do StaticFilter!(PApply(IsEqual, 5), …).
But yes, not being able to »chain« template instantiation is quite a limitation of the D grammar when it comes to »higher-order templates« (at least that's what I like to call them). In some situations, you have no other options than to define an Instantiate!() template, see e.g. the Gist I posted.
David
On 11/11/11 6:25 PM, David Nadlinger wrote:
> On 11/11/11 6:20 PM, Timon Gehr wrote:
>> This is a sketch of how I would approach your problem. The "Curry"
>> template automatically creates the nested template version from an
>> unnested one. You are then allowed to use both IsEqual!(val) and
>> IsEqual!(val1, val2).
>> […]
>
> See also: https://gist.github.com/1191885#L27
>
> Reminds me that I really have to put together a std.meta proposal – if I
> would only find time to do so…
>
> David
|
November 11, 2011 Re: How to implement predicates for Filter!(Pred, Tuple) | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | David Nadlinger wrote:
> To be more precise, Tobias, my PApply!() would allow you to define your
> predicate »unnested«, i.e. just as a template with two parameters and
> then do StaticFilter!(PApply(IsEqual, 5), …).
>
> But yes, not being able to »chain« template instantiation is quite a limitation of the D grammar when it comes to »higher-order templates« (at least that's what I like to call them). In some situations, you have no other options than to define an Instantiate!() template, see e.g. the Gist I posted.
>
> David
Awesome, thank you :) That should really make its way into phobos someday. However I wouldn't prefix everything with static, although it seems, that is the way phobos is going to do this. Instead I would use uppercase names for templates to distinguish them from normal functions.
|
November 11, 2011 Re: How to implement predicates for Filter!(Pred, Tuple) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | On 11/11/11 9:38 PM, Tobias Pankrath wrote:
> Awesome, thank you :) That should really make its way into phobos someday.
> However I wouldn't prefix everything with static, although it seems, that is
> the way phobos is going to do this. Instead I would use uppercase names for
> templates to distinguish them from normal functions.
I agree with you, prefixing stuff with Static… adds exactly no value. The problem is that Phobos defines quite a few types of similar names for the return type of the »dynamic« higher order functions (or rather defined, Andrei has been migrating them to »opaque« auto retuns), which could lead to confusion.
My plan was to drop any prefixes, simply calling the templates Map, Filter, and so on, choosing the case depending on whether a template/type/type-tuple or value is returned, and encourage users to use renamed imports for clarity in cases where it's not obvious (i.e. import meta = std.meta).
David
|
November 11, 2011 Re: How to implement predicates for Filter!(Pred, Tuple) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | On 11/11/11 9:38 PM, Tobias Pankrath wrote: > Awesome, thank you :) That should really make its way into phobos someday. > However I wouldn't prefix everything with static, although it seems, that is > the way phobos is going to do this. Instead I would use uppercase names for > templates to distinguish them from normal functions. Oh, and you might also be interested in this extended version which allows you to »skip« arguments, e.g. to bind only the second out of three parameters: https://gist.github.com/1359203 David |
Copyright © 1999-2021 by the D Language Foundation