Thread overview | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
September 27, 2010 [phobos] More tuple algorithms with std.meta | ||||
---|---|---|---|---|
| ||||
I'm willing to add more tuple algorithms to phobos for easing metaprogramming in D. Here's code and example: http://gist.github.com/598659 ---------- alias staticSort!( q{ a.at!(0).sizeof < b.at!(0).sizeof }, staticZip!( Wrap!(int, double, byte), Wrap!("x", "y", "z"))) A; pragma(msg, A); // tuple(Wrap!(byte,"z"),Wrap!(int,"x"),Wrap!(double,"y")) ---------- Built-in tuples have been able to store non-type compile-time entities. So, I propose we should rename the current TypeTuple to StaticTuple, and gather generic (non-type specific) tuple algorithms into a new module: std.meta. Does it sound good? Shin |
September 27, 2010 [phobos] More tuple algorithms with std.meta | ||||
---|---|---|---|---|
| ||||
Posted in reply to Shin Fujishiro | On Mon, 27 Sep 2010 02:17:19 -0400, Shin Fujishiro <rsinfu at gmail.com> wrote:
> I'm willing to add more tuple algorithms to phobos for easing metaprogramming in D. Here's code and example:
>
> http://gist.github.com/598659
>
> ----------
> alias staticSort!(
> q{ a.at!(0).sizeof < b.at!(0).sizeof },
> staticZip!( Wrap!(int, double, byte),
> Wrap!("x", "y", "z")))
> A;
> pragma(msg, A);
> // tuple(Wrap!(byte,"z"),Wrap!(int,"x"),Wrap!(double,"y"))
> ----------
>
> Built-in tuples have been able to store non-type compile-time entities. So, I propose we should rename the current TypeTuple to StaticTuple, and gather generic (non-type specific) tuple algorithms into a new module: std.meta.
>
> Does it sound good?
>
>
> Shin
> _______________________________________________
> phobos mailing list
> phobos at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/phobos
The meta namespace has been proposed as a possible replacement for __traits, etc. i.e. meta.compiles() vs __traits(compiles, ). So a different module name might be appropriate.
|
September 27, 2010 [phobos] More tuple algorithms with std.meta | ||||
---|---|---|---|---|
| ||||
Posted in reply to Shin Fujishiro | On Mon, Sep 27, 2010 at 08:17, Shin Fujishiro <rsinfu at gmail.com> wrote: > I'm willing to add more tuple algorithms to phobos for easing metaprogramming in D. Here's code and example: > > http://gist.github.com/598659 > > ---------- > alias staticSort!( > q{ a.at!(0).sizeof < b.at!(0).sizeof }, > staticZip!( Wrap!(int, double, byte), > Wrap!("x", "y", "z"))) > A; > pragma(msg, A); > // tuple(Wrap!(byte,"z"),Wrap!(int,"x"),Wrap!(double,"y")) > ---------- > > Built-in tuples have been able to store non-type compile-time entities. So, I propose we should rename the current TypeTuple to StaticTuple, and gather generic (non-type specific) tuple algorithms into a new module: std.meta. > > Does it sound good? > > > Shin > I'm willing to review your code. I also feel Phobos should showcase D metaprogramming on types. At a minimum, filtering, reducing, scanning (reduce with history), rotating and inverting tuples should be there. As for calling TypeTuple a StaticTuple, I prefer to keep TypeTuple. By convergent evolution, I have lots of template that do similar things to your and can confirm these are not just an intellectual exercise: as soon as you transform functions for example, you need to transform their parameters typetuple. The same for transforming a class/struct inner types, etc. I also choose to call them staticStuff, but it's becoming a bit cumbersome... Any idea to simplify the names would be welcome. I decided to separate those acting on typetuple and those acting on expression tuples / std.typecons.Tuple. My code is here: http://www.dsource.org/projects/dranges/browser/trunk/dranges/typetuple.d http://www.dsource.org/projects/dranges/browser/trunk/dranges/variadic.d http://www.dsource.org/projects/dranges/browser/trunk/dranges/tuple.d If think most templates dealing with type tuples (or rather, template arguments tuples) should go in std.typetuple. Those acting on expression tuples could go in std.variadic. Philippe -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.puremagic.com/pipermail/phobos/attachments/20100927/18ac3e82/attachment.html> |
September 28, 2010 [phobos] More tuple algorithms with std.meta | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | Philippe Sigaud <philippe.sigaud at gmail.com> wrote: > I'm willing to review your code. I also feel Phobos should showcase D metaprogramming on types. At a minimum, filtering, reducing, scanning (reduce with history), rotating and inverting tuples should be there. Thanks! Please note: D metaprogramming is not only on types, but also on symbols and compile-time constants - possibly combined with mixins. I mean, static tuple algorithms should be able to handle tuples composed of heterogeneous entities: types, symbols and/or constants. It will allow us to write something like follows in a short, functional style: Struct!(int, "x", double, "y") http://gist.github.com/600535 > I decided to separate those acting on typetuple and those acting on > expression tuples / std.typecons.Tuple. > My code is here: > > http://www.dsource.org/projects/dranges/browser/trunk/dranges/typetuple.d http://www.dsource.org/projects/dranges/browser/trunk/dranges/variadic.d http://www.dsource.org/projects/dranges/browser/trunk/dranges/tuple.d > > If think most templates dealing with type tuples (or rather, template > arguments tuples) should go in std.typetuple. > Those acting on expression tuples could go in std.variadic. I did know them. ;-) I thought of proposing your templates if someone was interested in this topic. (dranges.templates is interesting, too.) As for the separation of typetuple and variadic... As I mentioned above, I think static tuple algorithms should be able to work with heterogeneous tuples. Limiting algorithms only on types is not a choice for me. But it does *not* mean I think the variadic is useless! Note that I'm talking about compile-time operation on template tuple parameters; std.variadic algorithms would be definitely useful in run-time code. variadicMap is especially a gem! Shin |
September 28, 2010 [phobos] More tuple algorithms with std.meta | ||||
---|---|---|---|---|
| ||||
Posted in reply to Robert Jacques | "Robert Jacques" <sandford at jhu.edu> wrote:
> The meta namespace has been proposed as a possible replacement for __traits, etc. i.e. meta.compiles() vs __traits(compiles, ). So a different module name might be appropriate.
I'll consider. BTW, will this really happen, or rather is it necessary? IIRC, the proposal was against the ugly syntax. I think all the existing __traits except compiles could be wrapped with library templates with syntactic sanity and added flexibility. For example:
template getMember(alias Scope, string member)
{
alias Identity!(__traits(getMember, Scope, member)) getMember;
}
// This overload does partial application. Useful for staticMap etc.
template getMember(alias Scope)
{
template getMember(string member)
{
alias .getMember!(Scope, member) getMember;
}
}
Shin
|
September 28, 2010 [phobos] More tuple algorithms with std.meta | ||||
---|---|---|---|---|
| ||||
Posted in reply to Shin Fujishiro | On Tue, 28 Sep 2010 06:10:56 -0400, Shin Fujishiro <rsinfu at gmail.com> wrote:
> "Robert Jacques" <sandford at jhu.edu> wrote:
>> The meta namespace has been proposed as a possible replacement for
>> __traits, etc. i.e. meta.compiles() vs __traits(compiles, ). So a
>> different module name might be appropriate.
>
> I'll consider. BTW, will this really happen, or rather is it necessary? IIRC, the proposal was against the ugly syntax. I think all the existing __traits except compiles could be wrapped with library templates with syntactic sanity and added flexibility. For example:
>
>
> template getMember(alias Scope, string member)
> {
> alias Identity!(__traits(getMember, Scope, member)) getMember;
> }
>
> // This overload does partial application. Useful for staticMap etc.
> template getMember(alias Scope)
> {
> template getMember(string member)
> {
> alias .getMember!(Scope, member) getMember;
> }
> }
>
>
> Shin
I don't know if this is on the road map or not, I just remember a decently serious discussion about it. I do like your solution, although some __traits would require tuples of aliases and for aliases to support types in addition to expressions. Since we'd hopefully be able to do both some time in the future, no reason not to start a limited form of it now. Also, since things like getMember are fairly generic for the public namespace, they should probably be put into a holding struct (e.g. meta). This could also apply to your staticMap, staticReduce, etc. (i.e. meta.map and meta.reduce). This has the advantage of using with(meta){ } when large blocks of metaprogramming are written.
|
September 28, 2010 [phobos] More tuple algorithms with std.meta | ||||
---|---|---|---|---|
| ||||
Posted in reply to Robert Jacques | On Tue, Sep 28, 2010 at 16:52, Robert Jacques <sandford at jhu.edu> wrote: > > On Tue, 28 Sep 2010 06:10:56 -0400, Shin Fujishiro <rsinfu at gmail.com> wrote: > >> "Robert Jacques" <sandford at jhu.edu> wrote: >>> >>> The meta namespace has been proposed as a possible replacement for >>> __traits, etc. i.e. meta.compiles() vs __traits(compiles, ). So a >>> different module name might be appropriate. >> >> I'll consider. ?BTW, will this really happen, or rather is it necessary? IIRC, the proposal was against the ugly syntax. ?I think all the existing __traits except compiles could be wrapped with library templates with syntactic sanity and added flexibility. ?For example: >> >> >> template getMember(alias Scope, string member) >> { >> ? ?alias Identity!(__traits(getMember, Scope, member)) getMember; >> } >> >> // This overload does partial application. ?Useful for staticMap etc. >> template getMember(alias Scope) >> { >> ? ?template getMember(string member) >> ? ?{ >> ? ? ? ?alias .getMember!(Scope, member) getMember; >> ? ?} >> } Looking at it, most traits seems wrappable in this way, except 'compiles'. [meta] > I don't know if this is on the road map or not, I just remember a decently serious discussion about it. I do like your solution, although some __traits would require tuples of aliases and for aliases to support types in addition to expressions. Since we'd hopefully be able to do both some time in the future, no reason not to start a limited form of it now. Also, since things like getMember are fairly generic for the public namespace, they should probably be put into a holding struct (e.g. meta). This could also apply to your staticMap, staticReduce, etc. (i.e. meta.map and meta.reduce). This has the advantage of using with(meta){ } when large blocks of metaprogramming are written. And I find it easier on the eye to see meta.filter than staticFilter (even though I'm using the latter in my code). Philippe std.compiletime? |
September 28, 2010 [phobos] More tuple algorithms with std.meta | ||||
---|---|---|---|---|
| ||||
Posted in reply to Shin Fujishiro | On Tue, Sep 28, 2010 at 09:50, Shin Fujishiro <rsinfu at gmail.com> wrote: > Philippe Sigaud <philippe.sigaud at gmail.com> wrote: >> I'm willing to review your code. I also feel Phobos should showcase D metaprogramming on types. At a minimum, filtering, reducing, scanning (reduce with history), rotating and inverting tuples should be there. > > Thanks! ?Please note: D metaprogramming is not only on types, but also on symbols and compile-time constants - possibly combined with mixins. That's OK with me. What about I read and comment on your code before the end of the week? (Err, make that the very end of the week) > > I mean, static tuple algorithms should be able to handle tuples composed of heterogeneous entities: types, symbols and/or constants. Agreed. Ok, any compile-time sorcery on template-y arguments tuples. >?It will > allow us to write something like follows in a short, functional style: > > ?Struct!(int, "x", double, "y") > ?http://gist.github.com/600535 Nice! (I'd have filtered TypeNames to get types in a tuple and names in another, instead of striding TypeNames. But I say that only because I'm jealous of what you've done :) ) >?(dranges.templates is interesting, too.) having templates acting on templates is fun :) It's easy to do, too: meta-meta-programming, something that would have blown my mind in C++ :) > > As for the separation of typetuple and variadic... ?As I mentioned above, I think static tuple algorithms should be able to work with heterogeneous tuples. ?Limiting algorithms only on types is not a choice for me. OK. I indeed did them initially only as a way to generate types, when I was having troubles with auto. > > But it does *not* mean I think the variadic is useless! ?Note that I'm talking about compile-time operation on template tuple parameters; std.variadic algorithms would be definitely useful in run-time code. Banco for a separation between 'acting on tuples at CT' on one hand and 'acting on tuples at runtime' on another. > variadicMap is especially a gem! Thanks. That's strange, D has wonderfully powerful metaprogramming abilities, but no one seems to care. How many languages can offer a statically checked mapping of a polymorphic function on a heterogeneous list, in a few lines of code? And it's not just an esoteric goal: you can transform structs.tupleof or function arguments as you wish! Philippe |
September 28, 2010 [phobos] More tuple algorithms with std.meta | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | On 9/28/10 13:27 PDT, Philippe Sigaud wrote: > On Tue, Sep 28, 2010 at 09:50, Shin Fujishiro<rsinfu at gmail.com> wrote: >> Philippe Sigaud<philippe.sigaud at gmail.com> wrote: >> I mean, static tuple algorithms should be able to handle tuples composed >> of heterogeneous entities: types, symbols and/or constants. > > Agreed. Ok, any compile-time sorcery on template-y arguments tuples. I must say that a very healthy approach is to not be extravagant without solid use cases. There are lots of things that look cute and interesting in this style of programming, and getting carried away is probably the #1 risk. >> It will >> allow us to write something like follows in a short, functional style: >> >> Struct!(int, "x", double, "y") >> http://gist.github.com/600535 > > Nice! Isn't that as good as Tuple? > Thanks. That's strange, D has wonderfully powerful metaprogramming > abilities, but no one seems to care. How many languages can offer a > statically checked mapping of a polymorphic function on a > heterogeneous list, in a few lines of code? > And it's not just an esoteric goal: you can transform structs.tupleof > or function arguments as you wish! It's fine if the traction is little in the beginning. There has been very little initial traction for some stuff I've done too. Some never gained traction, but some did. If it's good, people will notice. Andrei |
October 03, 2010 [phobos] More tuple algorithms with std.meta | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | OK, Shin, I'm due a review of your code. Here it is: As a general note, I find it quite elegant, even though I found your constant use of a subdivide-and-recurse scheme a bit strange. It makes for some clean implementations, but also complicates matters in some cases. I'll indicate when I think a standard, linear implementation might be more readable. Also, maybe it'd be best if you introduced helper templates first. I believe Phobos does this. Anyway... l. 8: Why redefining TypeTuple as StaticTuple? I agree the name is a bit of a misnomer, but I'd prefer your module to use already defined templates if possible. l. 21-40: staticMap : instead of testing for seq.length<2 and then have a special case for == 0, I'd write test for == 0 else test for == 1 else (the rest) I grok Instantiate!template.With!arguments, but really in this case and many other, you just use a subcase. Why not do directly map!(seq[0])? Also, mapping is inherently linear n my mind, so using a dividing&recurse algorithm here seems strange. The same for filtering. l. 55: why seq and not seq[0]? Because you want the result to always be a tuple? l.93 (staticReduce).Ideally, there should be a 2-args version that takes seq[0] as a seed. l. 117: bindFront OK. Good one! l. 143: what is m? Is that the predicate's arity? That can be determined, given a template's symbol. So that could be done automatically here. l. 156: I suggest: enum size_t index = 0; l. 210: maybe you should test for pred being a binary template (arity == 2) l. 302 (staticCountIf): another example of recursing being strange to my eye. Cannot it just be staticFilter!(pred, seq).length? l. 304-316: I suggest to reorganize the code with * length == 0 * length == 1 * else l. 352 (_staticReplace(tr...): what if tr.length is not 2? Why not just do _staticReplace(from,to)? l. 354-355: what's the usefulness of Identity in this case? Cannot just "alias tr[0] from;" work? l. 377 (staticMost): it's a kind of fold, so it's implementable with staticReduce. Maybe staticReduce!(selectWith!comp, seq) with template selectWith(comp) { template selectWith(A,B) { static if (comp!(A,B) ) alias A selectWith; else alias B selctWith; } } or something like that, anyway. l. 384 & 388: why Identity? l. 414 (merge sort on tuples at CT): Nice one! l. 422 & 430, 432 & 437: Does the compiler know what template to instantiate for an empty tuple? I thought that was considered ambiguous? l. 439-448: I suggest to invert B and A in the test. Mostly, you want to do comp!(A[0],B[0]). And then do the then branch with A, the else branch with B. Looks more natural to me. l. 453: No, no ditto. l. 498 & 506, 508 & 513: No ambiguity for an empty tuple? l. 534: No, no ditto. l. 565: <2 might be better, to be consistent. l. 593: What's the difference with staticUniq? l. 595 here also, choose <=1 or <2, but stick with it for the entire module. l. 636-655: You know, I'd suggest a linear approach here. It'd be more readable and probaby reduce the number of lines. l. 664: why do you have staticStride return 1-element tuples instead of directly the elements? l. 679-681: for me, another example of the dividing/recursing algo complicating things greatly. You even have to introduce a helper template _strideMid. Why not just: alias StaticTuple!(seq[0], staticStride!(n, seq[n .. $])) staticStride; l. 699: you should test for .Expand being legal. Or maybe introduce a isTupleOfTuples template. Maybe implement staticTransverse with staticMap. As a general comment on the tuples-of-tuples code: there should be a way to segment a tuple into a tuple of n-elements tuples. l. 732: staticZip: good idea! I never had the energy to code this. staticZipWith would be cool. l. 763: staticPermutations: do you have a use case in mind? l. 765: (5 is the limit). Really? 120 5-tuplets is the limit? l. 781 & 787: I believe metaArray is not defined in the module. l. 879 / 884: same ambiguity question. Nice code, btw. l. 928-929: Once more, I don't find subdividing like this the most obvious way to code iota Having to introduce _iotaMid feels strange. l. 1000. Wrap is good, but I'd prefer not to introduce another Tuple-like template. I'd suggest using std.typecons.Tuple and extend it when possible. When that's not possible (as Tuple is a type and not a 'pure' template), use a free template. For example template insertFront(A, Tuple) l. 1113: Very clever, forcing the compiler to generates the two inner templates to compare the arguments. That's for being able to test aliases too, right? l. 1271 & 1280 (templateAnd, templateOr): These are quite useful, good idea to add them. I have the basis of a 'type pattern' module, to look for patterns in tuples, like for regexes. Maybe that could interest someone. alias Either!(int, OneOrMore!double, And!(string, double)) Pattern; // for example l. 1295 (templateCompose): Oh yes. Good job! Btw, I tested Robert's suggestion to put things in a struct called meta, and it worked: module metaprogramming; struct meta { template map { ... } } *-----------* module foo; import metaprogramming; void main() { alias meta.map!(isIntegral, int, double, string, byte) Result; writeln([Result]); } I find meta.* much cleaner than static* and such. Executive Summary: - Very nice code, very clever, lots of interesting things in there. Maybe sometimes too clever for a standard library, that should *also* be a way to learn the language. - Try to use some already-defined parts of Phobos. - Use a linear iteration scheme for some cases: dividing and recursing is not a panacea. - Maybe eliminate some 'less useful' templates, like staticPermutations unless you have a convincing use case. Philippe |
Copyright © 1999-2021 by the D Language Foundation