digitalmars.D - Proposal to add 'Elements of Programming' Concepts to std.traits
- Guillaume Chatelet (41/41) Jun 16 2012 'Elements of Programming' is an amazing book by Alexander Stepanov and
- bearophile (16/23) Jun 16 2012 That page looks quite interesting. I'll take a better look later
- Guillaume Chatelet (27/51) Jun 16 2012 The website is more of a stopgap, the book is way better because it
- bearophile (16/30) Jun 16 2012 I see. is that semantically different from this (beside being
- Guillaume Chatelet (12/27) Jun 16 2012 That's a good one ! I forgot about the _invariant_ keyword.
- bearophile (8/14) Jun 16 2012 I have proposed an idea to do something related in D (it's about
- Philippe Sigaud (7/18) Jun 16 2012 The invariant isn't invoked through alias this, it seems:
- Andrei Alexandrescu (4/22) Jun 17 2012 To avoid this, expose an rvalue via alias this, not an lvalue. Then
- Jonathan M Davis (6/26) Jun 16 2012 It wouldn't be. No public function was called. All you did was access th...
- Philippe Sigaud (7/10) Jun 17 2012 If I change
- Andrei Alexandrescu (3/15) Jun 17 2012 I'm surprised by such claims. I found EoP very easy to read.
- Guillaume Chatelet (13/16) Jun 17 2012 Ok let me restate this. First, those words are originally from Stepanov
- Walter Bright (13/17) Jun 16 2012 I have a nit to pick with that statement, as a former mechanical enginee...
- Guillaume Chatelet (9/33) Jun 16 2012 Thanks for sharing your experience, it's definitely an interesting point
- Denis Shelomovskij (11/21) Jun 18 2012 You all probably know a canonical example, Tacoma Narrows Bridge:
- Walter Bright (2/7) Jun 16 2012 I think you're on to some good stuff here.
- Jonathan M Davis (15/30) Jun 17 2012 Well, I'm not sure if it's supposed to be legal to access value like tha...
- Guillaume Chatelet (33/33) Jun 17 2012 That's a *lot* more code but I think we could do something like
- Philippe Sigaud (51/51) Jun 17 2012 On Sun, Jun 17, 2012 at 10:20 AM, Guillaume Chatelet
- Guillaume Chatelet (2/48) Jun 17 2012 Very nice :)
- Philippe Sigaud (18/27) Jun 17 2012 The new syntax for lambdas is delightful to use. A bunch of aliases
- Guillaume Chatelet (5/23) Jun 17 2012 I ran into that problem also. I usually tend to define a function for
- Timon Gehr (4/27) Jun 17 2012 I have reported this bug a few days ago:
- Philippe Sigaud (9/15) Jun 17 2012 luck
- Andrei Alexandrescu (4/6) Jun 17 2012 Nice idea, but it should be said that making the predicate opaque
- Andrei Alexandrescu (22/29) Jun 17 2012 This is a good idea because the traits are useful within and outside the...
- Guillaume Chatelet (6/31) Jun 17 2012 What would you recommend ?
- Guillaume Chatelet (23/31) Jun 17 2012 Yes. As you noticed CoDomain is simply an alias to ReturnType.
- Andrei Alexandrescu (30/63) Jun 17 2012 That's great. On the other hand D is not C++, and it naturally fosters a...
- Guillaume Chatelet (7/19) Jun 22 2012 So here it is. A first very small patch to add arity to std.traits.
- Guillaume Chatelet (3/25) Jun 22 2012 It's better with a link :-P
- Andrei Alexandrescu (3/21) Jun 27 2012 Great. You should know I'm on vacation with scant access to email.
'Elements of Programming' is an amazing book by Alexander Stepanov and Paul McJones ( M. Stepanov is the primary designer of the C++ STL ). Here is a rather long but insightful comment about the book : "Ask a mechanical, structural, or electrical engineer how far they would get without a heavy reliance on a firm mathematical foundation, and they will tell you, not far. Yet so-called software engineers often practice their art with little or no idea of the mathematical underpinnings of what they are doing. And then we wonder why software is notorious for being delivered late and full of bugs, while other engineers routinely deliver finished bridges, automobiles, electrical appliances, etc., on time and with only minor defects. This book sets out to redress this imbalance.[...]" Martin Newell, Adobe Fellow The book carefully crafts foundations for designing efficient, mathematically sound and generic algorithms. Apart from the fact this book is an absolute must read, I think the D community could really benefit from integrating these concepts. A minimalistic website maintains the concepts defined so far and the C++ code http://www.elementsofprogramming.com/ As an exercise I started to port the books concepts to D and the mathematical constructs do really fit nicely within the language. * D's purity can bring some guaranties that C++ can't ( see the definition for FunctionalProcedure in http://www.elementsofprogramming.com/eop-concepts.pdf ) * D's structs being value semantic, default constructible simplifies a lot. * Concepts translation into D's templates is very readable and straightforward. Now on the downside, D being a C-style-system-language, we won't be able to prevent implicit lossy conversions or add value domain constrains as in the X10 language for instance. But nonetheless I think it's still a worthwhile goal to seek. It would give more confidence in the code, both on correctness and genericity sides. So without further ado, here is my humble first attempt https://github.com/gchatelet/phobos/blob/traits_concepts/std/traits2.d And the associated more readable DDoc http://bbteam.fr/traits2.html I would like to hear what you think. Note : It's called traits2 because of a lack of inspiration not because I intend it to replace std.traits. -- Guillaume
Jun 16 2012
Guillaume Chatelet:A minimalistic website maintains the concepts defined so far and the C++ code http://www.elementsofprogramming.com/That page looks quite interesting. I'll take a better look later (I have not read that book). In a recent (probably no more than one year old) talk by Bjarne Stroustrup, he has shown a list of concepts that fits mostly in one slide. So he has significantly reduced the number of Concepts needed for the STL.Now on the downside, D being a C-style-system-language, we won't be able to prevent implicit lossy conversionsD disallows some implicit conversions (float => int, int => short, etc). The conversions like uint=>int and int=>uint are an open problem, waiting for some solution (a simple "solution" is to add a warning, as in GCC. It's not a great solution, but maybe it's better than the current D situation).or add value domain constrains as in the X10 language for instance.Please explain, don't assume all people here know X10. Bye, bearophile
Jun 16 2012
On 06/16/12 17:58, bearophile wrote:Guillaume Chatelet:The website is more of a stopgap, the book is way better because it shows the paths from concepts to concepts. I should warn the book is not easy to read, it's hard and it hurts, but it's good hurt.A minimalistic website maintains the concepts defined so far and the C++ code http://www.elementsofprogramming.com/That page looks quite interesting. I'll take a better look later (I have not read that book).In a recent (probably no more than one year old) talk by Bjarne Stroustrup, he has shown a list of concepts that fits mostly in one slide. So he has significantly reduced the number of Concepts needed for the STL.Yes, you can hear him speak about it there http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/A-Concept-Design-for-C- His proposal is also available ( also I'm not sure it's in sync with the video ) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3351.pdf My main regrets regarding this proposal : * pervasive use of iterators instead of a more safe Range abstraction. * duplication of code with the xxxx_if variants ( all functions could take a default predicate evaluating to constexp true ).Yes it's been debated several times on the ML and I agree a compiler warning could do. Every serious developer should toggle warning-as-errors anyway.Now on the downside, D being a C-style-system-language, we won't be able to prevent implicit lossy conversionsD disallows some implicit conversions (float => int, int => short, etc). The conversions like uint=>int and int=>uint are an open problem, waiting for some solution (a simple "solution" is to add a warning, as in GCC. It's not a great solution, but maybe it's better than the current D situation).Sorry about that, you're absolutely right. X10 ( http://x10-lang.org/ ) allows user to add constrains on value domain definition at declaration time. Here are a few lines took from the documentation : * Int{self != 0} is the type of non-zero Ints. * Int{self != 0, self != 1} is the type of Ints which are neither zero nor one. * String{self != null} is the type of non-null strings. * Matrix{self.rows == self.cols} is the type of square matrices. -- Guillaumeor add value domain constrains as in the X10 language for instance.Please explain, don't assume all people here know X10.
Jun 16 2012
Guillaume Chatelet:The website is more of a stopgap, the book is way better because it shows the paths from concepts to concepts. I should warn the book is not easy to read, it's hard and it hurts, but it's good hurt.I like hard books, if they give something valuable back.X10 ( http://x10-lang.org/ ) allows user to add constrains on value domain definition at declaration time. Here are a few lines took from the documentation : * Int{self != 0} is the type of non-zero Ints. * Int{self != 0, self != 1} is the type of Ints which are neither zero nor one. * String{self != null} is the type of non-null strings. * Matrix{self.rows == self.cols} is the type of square matrices.I see. is that semantically different from this (beside being shorter)? struct NoZero { int value; this(int x) { value = x; } alias value this; invariant() { assert(value != 0); } } void main() { auto a = NoZero(5); auto b = NoZero(0); } Bye, bearophile
Jun 16 2012
On 06/16/12 21:22, bearophile wrote:Guillaume Chatelet: I like hard books, if they give something valuable back.I think you'll find it rewarding.I see. is that semantically different from this (beside being shorter)? struct NoZero { int value; this(int x) { value = x; } alias value this; invariant() { assert(value != 0); } } void main() { auto a = NoZero(5); auto b = NoZero(0); }That's a good one ! I forgot about the _invariant_ keyword. It's pretty close. For what I understood of x10 (I'm not using it yet just interested in the language) the compiler will also enforce the invariance at compile time not solely at runtime. ie void main(){ NoZero a = 0; // shouldn't compile } Thx for the design though, I keep it in my toolbox. -- Guillaume
Jun 16 2012
Guillaume Chatelet:It's pretty close. For what I understood of x10 (I'm not using it yet just interested in the language) the compiler will also enforce the invariance at compile time not solely at runtime. ie void main(){ NoZero a = 0; // shouldn't compile }I have proposed an idea to do something related in D (it's about pre-conditions, not invariants, but this is an easy problem to solve, adding assign/read methods to that NoZero, and giving them pre-conditions): http://d.puremagic.com/issues/show_bug.cgi?id=5906 Bye, bearophile
Jun 16 2012
On Sat, Jun 16, 2012 at 9:22 PM, bearophile <bearophileHUGS lycos.com> wrot= e:I see. is that semantically different from this (beside being shorter)? struct NoZero { =C2=A0 =C2=A0int value; =C2=A0 =C2=A0this(int x) { value =3D x; } =C2=A0 =C2=A0alias value this; =C2=A0 =C2=A0invariant() { assert(value !=3D 0); } } void main() { =C2=A0 =C2=A0auto a =3D NoZero(5); =C2=A0 =C2=A0auto b =3D NoZero(0); }The invariant isn't invoked through alias this, it seems: void main() { auto a =3D NoZero(5); a =3D 0; // compiles and runs happily }
Jun 16 2012
On 6/17/12 1:38 AM, Philippe Sigaud wrote:On Sat, Jun 16, 2012 at 9:22 PM, bearophile<bearophileHUGS lycos.com> wrote:To avoid this, expose an rvalue via alias this, not an lvalue. Then implement opAssign etc. AndreiI see. is that semantically different from this (beside being shorter)? struct NoZero { int value; this(int x) { value = x; } alias value this; invariant() { assert(value != 0); } } void main() { auto a = NoZero(5); auto b = NoZero(0); }The invariant isn't invoked through alias this, it seems: void main() { auto a = NoZero(5); a = 0; // compiles and runs happily }
Jun 17 2012
On Sunday, June 17, 2012 08:38:41 Philippe Sigaud wrote:On Sat, Jun 16, 2012 at 9:22 PM, bearophile <bearophileHUGS lycos.com>wrote:It wouldn't be. No public function was called. All you did was access the public member variable. Having public members and invariants at the same time doesn't work very well. - Jonathan M DavisI see. is that semantically different from this (beside being shorter)? struct NoZero { int value; this(int x) { value = x; } alias value this; invariant() { assert(value != 0); } } void main() { auto a = NoZero(5); auto b = NoZero(0); }The invariant isn't invoked through alias this, it seems: void main() { auto a = NoZero(5); a = 0; // compiles and runs happily }
Jun 16 2012
On Sun, Jun 17, 2012 at 8:42 AM, Jonathan M Davis <jmdavisProg gmx.com> wrote:It wouldn't be. No public function was called. All you did was access the public member variable. Having public members and invariants at the same time doesn't work very well.If I change int value; to private int value; it can still be accessed through alias this (I guess) and no invariant is called.
Jun 17 2012
On 6/16/12 11:29 AM, Guillaume Chatelet wrote:On 06/16/12 17:58, bearophile wrote:I'm surprised by such claims. I found EoP very easy to read. AndreiGuillaume Chatelet:The website is more of a stopgap, the book is way better because it shows the paths from concepts to concepts. I should warn the book is not easy to read, it's hard and it hurts, but it's good hurt.A minimalistic website maintains the concepts defined so far and the C++ code http://www.elementsofprogramming.com/That page looks quite interesting. I'll take a better look later (I have not read that book).
Jun 17 2012
On 06/17/12 18:41, Andrei Alexandrescu wrote:I'm surprised by such claims. I found EoP very easy to read. AndreiOk let me restate this. First, those words are originally from Stepanov himself "This is not an easy book" is explicitly written in the inner cover :) Then it's not a *difficult* book if you have a mathematical background - any engineer degree would do - but if you came to programming from a different path, you'd probably find it queasy. I don't expect anyone in this forum to have this background thus the disclaimer but I may be wrong. Moreover if you intend to read it the way it's planned by the author (doing the exercises and proving the lemmas) it's not as fun as reading TDPL. Let's say you need to think while reading, a bit like for 'Modern C++ design'. I hope these few lines gives a more comprehensive view of what I meant and won't discourage anyone from reading it.
Jun 17 2012
On 6/16/2012 8:26 AM, Guillaume Chatelet wrote:And then we wonder why software is notorious for being delivered late and full of bugs, while other engineers routinely deliver finished bridges, automobiles, electrical appliances, etc., on time and with only minor defects.I have a nit to pick with that statement, as a former mechanical engineer who has done professional mechanical designs and has taken apart a lot of others. Bridges, automobiles, electrical appliances, etc., are full of design errors. The engineers who design them aren't any smarter, more professional, or rely on mathematical precision any more than software engineers do. In fact, quite a large fraction of them can do math little more advanced than simple arithmetic. They don't catastrophically fail that often simply because they are way, way overdesigned. A bridge, for example, can withstand several times its design load. That covers an awful lot of sins. Software, on the other hand, can catastrophically fail with the slightest mistake - a single bit being off. The "on time" is equally misinformed. The more new design there is in other engineering projects, the more certain it is to be late.
Jun 16 2012
On 06/16/12 18:11, Walter Bright wrote:On 6/16/2012 8:26 AM, Guillaume Chatelet wrote:Thanks for sharing your experience, it's definitely an interesting point of view.And then we wonder why software is notorious for being delivered late and full of bugs, while other engineers routinely deliver finished bridges, automobiles, electrical appliances, etc., on time and with only minor defects.I have a nit to pick with that statement, as a former mechanical engineer who has done professional mechanical designs and has taken apart a lot of others. Bridges, automobiles, electrical appliances, etc., are full of design errors. The engineers who design them aren't any smarter, more professional, or rely on mathematical precision any more than software engineers do. In fact, quite a large fraction of them can do math little more advanced than simple arithmetic.They don't catastrophically fail that often simply because they are way, way overdesigned. A bridge, for example, can withstand several times its design load. That covers an awful lot of sins. Software, on the other hand, can catastrophically fail with the slightest mistake - a single bit being off.Yes. My former studies were also in mechanical engineering so I tend to agree - even if I never done it professionally. Security margins are 'everywhere' from pins to ball bearings...The "on time" is equally misinformed. The more new design there is in other engineering projects, the more certain it is to be late.Completely agree here, because you can't rely on a previous experience it's almost impossible to have an accurate estimation of the schedule, even with huge margin on your side :)
Jun 16 2012
16.06.2012 20:11, Walter Bright пишет:On 6/16/2012 8:26 AM, Guillaume Chatelet wrote:You all probably know a canonical example, Tacoma Narrows Bridge: http://www.youtube.com/watch?v=j-zczJXSxnw Let's forgive its designers because it was the first such accident with bridge. But in Russia we still (2010) have this: http://www.youtube.com/watch?v=rVzYDIlBQ0w And this bridge still works without rebuilding, but with attenuator now. -- Денис В. Шеломовский Denis V. ShelomovskijAnd then we wonder why software is notorious for being delivered late and full of bugs, while other engineers routinely deliver finished bridges, automobiles, electrical appliances, etc., on time and with only minor defects.I have a nit to pick with that statement, as a former mechanical engineer who has done professional mechanical designs and has taken apart a lot of others. Bridges, automobiles, electrical appliances, etc., are full of design errors.
Jun 18 2012
On 6/16/2012 8:26 AM, Guillaume Chatelet wrote:So without further ado, here is my humble first attempt https://github.com/gchatelet/phobos/blob/traits_concepts/std/traits2.d And the associated more readable DDoc http://bbteam.fr/traits2.html I would like to hear what you think.I think you're on to some good stuff here.
Jun 16 2012
On Sunday, June 17, 2012 09:04:16 Philippe Sigaud wrote:On Sun, Jun 17, 2012 at 8:42 AM, Jonathan M Davis <jmdavisProg gmx.com>wrote:Well, I'm not sure if it's supposed to be legal to access value like that if it's private, but public or private has nothing to do with the invariant in this case. The invariant only runs when you call public _functions_ (it may be run with package and protected as well - I don't recall - but never with private). It's run before and after they're executed. You're accessing a member _variable_. That's why the invariant isn't run. It doesn't matter what the access level of a variable is, the invariant is never run just because you accessed it. That's why if you want to be able to guarantee your invariants, you should never have public member variables on types with an invariant. And if alias this allows you to expose a private member variable, then it's in the same boat as a public one. Invariants and public member variables just don't mix. - Jonathan M DavisIt wouldn't be. No public function was called. All you did was access the public member variable. Having public members and invariants at the same time doesn't work very well.If I change int value; to private int value; it can still be accessed through alias this (I guess) and no invariant is called.
Jun 17 2012
That's a *lot* more code but I think we could do something like struct NoZero { private int _value; invariant() { assert(_value != 0); } this(int x) { _value = x; } NoZero opBinary(string op)(const ref NoZero rhs) { return NoZero(mixin("this._value"~op~"rhs._value")); } NoZero opBinary(string op)(int rhs) { return NoZero(mixin("this._value"~op~"rhs")); } ref NoZero opUnary(string op)() if(op=="++"||op=="--"){ mixin(op~"this._value;"); return this; } ref NoZero opAssign(int rhs) { value = rhs; return this; } property int value() const { return _value; } property void value(int newValue) { _value = newValue; } alias this value; } void main(){ NoZero a = 1; auto b = a; // copyable // --b; would assert auto c = b+1; auto d = c+a; } Note the implementation is incomplete, still need to implement comparison to bool, operator'!' , unary '+', '-', '~', checks for overflows. It's a bit of work but I think it can be done.
Jun 17 2012
On Sun, Jun 17, 2012 at 10:20 AM, Guillaume Chatelet <chatelet.guillaume gmail.com> wrote: Nice. You can also add: this(NoZero nz) { _value = nz._value; } and ref NoZero opAssign(NoZero rhs) { value = rhs._value; return this; } this allows code like this: a = a-a; // asserts a = a*0; // asserts An obvious generalization is to template the struct on a predicate: struct Constrained(T, alias pred) { private T _value; invariant() { assert(pred(_value)); } this(T x) { _value = x; } this(Constrained c) { _value = c._value; } Constrained opBinary(string op)(const ref Constrained rhs) { return Constrained(mixin("this._value"~op~"rhs._value")); } Constrained opBinary(string op)(T rhs) { return Constrained(mixin("this._value"~op~"rhs")); } ref Constrained opUnary(string op)() if(op=="++"||op=="--"){ mixin(op~"this._value;"); return this; } ref Constrained opAssign(T rhs) { value = rhs; return this; } ref Constrained opAssign(Constrained rhs) { value = rhs._value; return this; } property T value() const { return _value; } property void value(T newValue) { _value = newValue; } alias this value; } Constrained!(T,pred) constrained(alias pred, T)(T _value){ return typeof(return)(_value); } void main(){ auto a = constrained!(x => x > 0)(1); auto b = a; auto c = b+1; auto d = c+a; a = b-d; }
Jun 17 2012
On 06/17/12 14:23, Philippe Sigaud wrote:An obvious generalization is to template the struct on a predicate: struct Constrained(T, alias pred) { private T _value; invariant() { assert(pred(_value)); } this(T x) { _value = x; } this(Constrained c) { _value = c._value; } Constrained opBinary(string op)(const ref Constrained rhs) { return Constrained(mixin("this._value"~op~"rhs._value")); } Constrained opBinary(string op)(T rhs) { return Constrained(mixin("this._value"~op~"rhs")); } ref Constrained opUnary(string op)() if(op=="++"||op=="--"){ mixin(op~"this._value;"); return this; } ref Constrained opAssign(T rhs) { value = rhs; return this; } ref Constrained opAssign(Constrained rhs) { value = rhs._value; return this; } property T value() const { return _value; } property void value(T newValue) { _value = newValue; } alias this value; } Constrained!(T,pred) constrained(alias pred, T)(T _value){ return typeof(return)(_value); } void main(){ auto a = constrained!(x => x > 0)(1); auto b = a; auto c = b+1; auto d = c+a; a = b-d; }Very nice :)
Jun 17 2012
On Sun, Jun 17, 2012 at 3:11 PM, Guillaume Chatelet <chatelet.guillaume gmail.com> wrote:On 06/17/12 14:23, Philippe Sigaud wrote:The new syntax for lambdas is delightful to use. A bunch of aliases should give you the X10 examples. x =3D> ... still has some problem as it's a template, but using a standard module-level function gives functionalities akin to X10: bool pos(int x) { return x > 0;} alias Constrained!(int, pos) Positive; // works // alias Constrained!(int, (int x) { return x > 0;}) Positive; // works // alias Constrained!(int, (int x) =3D> x > 0) Positive; // works // but: // alias Constrained!(int, (x) { return x > 0;}) Positive; // ka-boom! // alias Constrained!(int, x =3D> x > 0) Positive; // no such luck enum OK =3D Positive(1); // OK enum NOK =3D Positive(-1); // Compiling error, cool! So this works. That's nice to know, I never used an assert inside a CT evaluation. Hmmm, validating XML and/or SQL queries at CT...void main(){ =C2=A0 =C2=A0auto a =3D constrained!(x =3D> x > 0)(1); =C2=A0 =C2=A0auto b =3D a; =C2=A0 =C2=A0auto c =3D b+1; =C2=A0 =C2=A0auto d =3D c+a; =C2=A0 =C2=A0a =3D b-d; // Boom! }Very nice :)
Jun 17 2012
On 06/17/12 15:53, Philippe Sigaud wrote:x => ... still has some problem as it's a template, but using a standard module-level function gives functionalities akin to X10: bool pos(int x) { return x > 0;} alias Constrained!(int, pos) Positive; // works // alias Constrained!(int, (int x) { return x > 0;}) Positive; // works // alias Constrained!(int, (int x) => x > 0) Positive; // works // but: // alias Constrained!(int, (x) { return x > 0;}) Positive; // ka-boom! // alias Constrained!(int, x => x > 0) Positive; // no such luckI ran into that problem also. I usually tend to define a function for readability. It would be nice to have it working though, the last one is definitely neat.enum OK = Positive(1); // OK enum NOK = Positive(-1); // Compiling error, cool! So this works. That's nice to know, I never used an assert inside a CT evaluation. Hmmm, validating XML and/or SQL queries at CT...Yummy !
Jun 17 2012
On 06/17/2012 03:53 PM, Philippe Sigaud wrote:On Sun, Jun 17, 2012 at 3:11 PM, Guillaume Chatelet <chatelet.guillaume gmail.com> wrote:I have reported this bug a few days ago: http://d.puremagic.com/issues/show_bug.cgi?id=8242 Apparently, Kenji Hara has already fixed it.On 06/17/12 14:23, Philippe Sigaud wrote:The new syntax for lambdas is delightful to use. A bunch of aliases should give you the X10 examples. x => ... still has some problem as it's a template, but using a standard module-level function gives functionalities akin to X10: bool pos(int x) { return x> 0;} alias Constrained!(int, pos) Positive; // works // alias Constrained!(int, (int x) { return x> 0;}) Positive; // works // alias Constrained!(int, (int x) => x> 0) Positive; // works // but: // alias Constrained!(int, (x) { return x> 0;}) Positive; // ka-boom! // alias Constrained!(int, x => x> 0) Positive; // no such luckvoid main(){ auto a = constrained!(x => x> 0)(1); auto b = a; auto c = b+1; auto d = c+a; a = b-d; // Boom! }Very nice :)
Jun 17 2012
On Sun, Jun 17, 2012 at 6:39 PM, Timon Gehr <timon.gehr gmx.ch> wrote:om!// alias Constrained!(int, (x) { return x> =C2=A00;}) Positive; // ka-bo=luck// alias Constrained!(int, x =3D> =C2=A0x> =C2=A00) Positive; // no such=No wonder, it takes him about 23 minutes, on average, to fix bugs once they are reported :) But, if he really fixed it (in the general case, lambda context botch and all), then he just corrected one of the most annoying bugs as far as I'm concerned. I hit it in every D project I have. Then I'll be, once more, forever grateful to Kenji Hara.I have reported this bug a few days ago: http://d.puremagic.com/issues/show_bug.cgi?id=3D8242 Apparently, Kenji Hara has already fixed it.
Jun 17 2012
On 6/17/12 7:23 AM, Philippe Sigaud wrote:An obvious generalization is to template the struct on a predicate: struct Constrained(T, alias pred) {Nice idea, but it should be said that making the predicate opaque prevents the implementer from taking advantage of its properties. Andrei
Jun 17 2012
On 6/16/12 10:26 AM, Guillaume Chatelet wrote:'Elements of Programming' is an amazing book by Alexander Stepanov and Paul McJones ( M. Stepanov is the primary designer of the C++ STL ).[snip]So without further ado, here is my humble first attempt https://github.com/gchatelet/phobos/blob/traits_concepts/std/traits2.d And the associated more readable DDoc http://bbteam.fr/traits2.html I would like to hear what you think.This is a good idea because the traits are useful within and outside the algorithms discussed in EoP. However, I don't think we need to abide strictly to the nomenclature (e.g. some of the stuff in EoP was already defined with a different name) although some EoP names are more mathematicky (such as "Codomain" vs. "ReturnType"). One issue is when EoP goes off and defines its own terms such as "regular type", which is usually known as "value type". In fact, "regular type" means something completely different in PL research. EoP's terminology didn't catch up outside C++ and sometimes outside a small group within it. If I'm allowed to venture an opinion on EoP itself, it's an interesting book but I don't find it as big or great as some of its fans believe. It's not breaking any new ground, instead it explores more along already well-trodden territory, and it fails to find new mother lodes. Some (many?) chapters (such as transformations and orbits) describe some self-important notions but fail to demonstrate their general applicability. Nevertheless, the code really is exquisitely written, and studying it has significantly changed my approach and style in implementing algorithms. Andrei
Jun 17 2012
On 06/17/12 18:38, Andrei Alexandrescu wrote:This is a good idea because the traits are useful within and outside the algorithms discussed in EoP. However, I don't think we need to abide strictly to the nomenclature (e.g. some of the stuff in EoP was already defined with a different name) although some EoP names are more mathematicky (such as "Codomain" vs. "ReturnType"). One issue is when EoP goes off and defines its own terms such as "regular type", which is usually known as "value type". In fact, "regular type" means something completely different in PL research. EoP's terminology didn't catch up outside C++ and sometimes outside a small group within it. If I'm allowed to venture an opinion on EoP itself, it's an interesting book but I don't find it as big or great as some of its fans believe. It's not breaking any new ground, instead it explores more along already well-trodden territory, and it fails to find new mother lodes. Some (many?) chapters (such as transformations and orbits) describe some self-important notions but fail to demonstrate their general applicability. Nevertheless, the code really is exquisitely written, and studying it has significantly changed my approach and style in implementing algorithms. AndreiWhat would you recommend ? Something more practical as Stroustrup and Sutton N3351's proposal : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3351.pdf We can also get inspired by Sutton's origin project : http://code.google.com/p/origin
Jun 17 2012
On 06/17/12 18:38, Andrei Alexandrescu wrote:However, I don't think we need to abide strictly to the nomenclature (e.g. some of the stuff in EoP was already defined with a different name) although some EoP names are more mathematicky (such as "Codomain" vs. "ReturnType"). One issue is when EoP goes off and defines its own terms such as "regular type", which is usually known as "value type". In fact, "regular type" means something completely different in PL research. EoP's terminology didn't catch up outside C++ and sometimes outside a small group within it.Yes. As you noticed CoDomain is simply an alias to ReturnType. The purpose of this thread was to measure the interest of the D community in going further in this direction. I thought it would be great to benefit from the work the C++ community has already done in this domain. Brilliant people are working on it for years and the more basic Concepts look stable now so it might be a good starting point. My take on it is that Concept modeling improves in designing and extending complex generic libraries. As an example see the Generic Image Library (GIL) by Adobe and now part of Boost. http://stlab.adobe.com/gil/html/gildesignguide.html Of course, the idioms being different, I was also looking for some feedback. I did ask myself what naming convention should be used considering some traits were already implemented as you pointed out. I sticked to the D _isXXXX_ convention instead of the plain CamelCase name. I was tempted to use a _hasValueSemantic_ traits (Concept) instead of _isRegular_. Also _isPure_ could replace _isFunctionalProcedure_. Basically this is just a proposal and everything can change at this point. I'm also not convinced we should add every single Concepts Stepanov is describing, we have to be pragmatic here. So what do you think should be the next move ? Try to integrate those concepts within phobos ? try to add more of them ? More comments are definitely welcome. Many thanks for everyones feedback.
Jun 17 2012
On 6/17/12 4:47 PM, Guillaume Chatelet wrote:On 06/17/12 18:38, Andrei Alexandrescu wrote:That's great. On the other hand D is not C++, and it naturally fosters a different dynamics of idioms. D has static if and restricted templates, which are the concept equivalent of lambda functions. That changes the play field considerably because in C++ the syntactic overhead of expressing any constraint is so high, the normal tendency is to name everything. In D, you only need to name things that are often used and relatively complex. So I don't think copying the laundry list of C++ concepts is the best way to go, because some of those overcome insufficiencies that are obviated by D. Nevertheless, a good design is a good design, and we could and should use is as inspiration.However, I don't think we need to abide strictly to the nomenclature (e.g. some of the stuff in EoP was already defined with a different name) although some EoP names are more mathematicky (such as "Codomain" vs. "ReturnType"). One issue is when EoP goes off and defines its own terms such as "regular type", which is usually known as "value type". In fact, "regular type" means something completely different in PL research. EoP's terminology didn't catch up outside C++ and sometimes outside a small group within it.Yes. As you noticed CoDomain is simply an alias to ReturnType. The purpose of this thread was to measure the interest of the D community in going further in this direction. I thought it would be great to benefit from the work the C++ community has already done in this domain. Brilliant people are working on it for years and the more basic Concepts look stable now so it might be a good starting point.My take on it is that Concept modeling improves in designing and extending complex generic libraries. As an example see the Generic Image Library (GIL) by Adobe and now part of Boost. http://stlab.adobe.com/gil/html/gildesignguide.html Of course, the idioms being different, I was also looking for some feedback. I did ask myself what naming convention should be used considering some traits were already implemented as you pointed out. I sticked to the D _isXXXX_ convention instead of the plain CamelCase name.I think either way is fine. One convention I tried to foster was to name all symbols that ultimately expand to values starting with a lowercase, e.g. isXXX or hasXXX, and symbols that ultimately yield non-values should start with an uppercase, e.g. Unsigned or Unqual.I was tempted to use a _hasValueSemantic_ traits (Concept) instead of _isRegular_.I personally would love that. Honest I think isRegular is provincial. Just google for "regular type" to see what I mean.Also _isPure_ could replace _isFunctionalProcedure_. Basically this is just a proposal and everything can change at this point. I'm also not convinced we should add every single Concepts Stepanov is describing, we have to be pragmatic here.Awesome, my thoughts above (written before I saw this paragraph) reflect the same view.So what do you think should be the next move ? Try to integrate those concepts within phobos ? try to add more of them ? More comments are definitely welcome. Many thanks for everyones feedback.I think traits are something that we could add piecemeal, without a large proposal - just as pull requests. For each particular concept there should be 1-2 compelling examples in the documentation, enough to make a case that the notion being added is worthwhile. For a simple example I'd like "arity" (I'm unclear whether it belongs in std.traits or std.functional). Sure, I could write ParameterTypeTuple!fun.length, but that's quite a roundabout way to go about it. Andrei
Jun 17 2012
On 06/18/12 04:18, Andrei Alexandrescu wrote:I think traits are something that we could add piecemeal, without a large proposal - just as pull requests. For each particular concept there should be 1-2 compelling examples in the documentation, enough to make a case that the notion being added is worthwhile. For a simple example I'd like "arity" (I'm unclear whether it belongs in std.traits or std.functional). Sure, I could write ParameterTypeTuple!fun.length, but that's quite a roundabout way to go about it. AndreiSo here it is. A first very small patch to add arity to std.traits. As you stated it could really go either in std.traits or std.functional. I chose to keep it in std.traits because std.functional is more about creating new functions of modifying existing ones whereas std.traits is about deducing properties. Guillaume
Jun 22 2012
On 06/22/12 23:37, Guillaume Chatelet wrote:On 06/18/12 04:18, Andrei Alexandrescu wrote:It's better with a link :-P https://github.com/D-Programming-Language/phobos/pull/643I think traits are something that we could add piecemeal, without a large proposal - just as pull requests. For each particular concept there should be 1-2 compelling examples in the documentation, enough to make a case that the notion being added is worthwhile. For a simple example I'd like "arity" (I'm unclear whether it belongs in std.traits or std.functional). Sure, I could write ParameterTypeTuple!fun.length, but that's quite a roundabout way to go about it. AndreiSo here it is. A first very small patch to add arity to std.traits. As you stated it could really go either in std.traits or std.functional. I chose to keep it in std.traits because std.functional is more about creating new functions of modifying existing ones whereas std.traits is about deducing properties. Guillaume
Jun 22 2012
On 6/22/12 5:37 PM, Guillaume Chatelet wrote:On 06/18/12 04:18, Andrei Alexandrescu wrote:Great. You should know I'm on vacation with scant access to email. AndreiI think traits are something that we could add piecemeal, without a large proposal - just as pull requests. For each particular concept there should be 1-2 compelling examples in the documentation, enough to make a case that the notion being added is worthwhile. For a simple example I'd like "arity" (I'm unclear whether it belongs in std.traits or std.functional). Sure, I could write ParameterTypeTuple!fun.length, but that's quite a roundabout way to go about it. AndreiSo here it is. A first very small patch to add arity to std.traits. As you stated it could really go either in std.traits or std.functional. I chose to keep it in std.traits because std.functional is more about creating new functions of modifying existing ones whereas std.traits is about deducing properties.
Jun 27 2012