digitalmars.D - Too many attributes?
- Janice Caron (86/89) Apr 25 2008 You're not the only one.
- Yigal Chripun (21/37) Apr 25 2008 My example was a contrived one, but you provided good examples that
- Christian Kamm (4/10) Apr 25 2008 For what it's worth, the D spec 2.013 allows delegates to have the pure ...
- Janice Caron (9/11) Apr 25 2008 On 25/04/2008, Christian Kamm
- Bruno Medeiros (7/38) Apr 29 2008 Another example why "scoped const", despite "only" being a syntactical
- Janice Caron (4/6) Apr 29 2008 That wouldn't help in this case. The reason you need the second
- Bruno Medeiros (15/22) Apr 29 2008 Not if you combine "scoped const" with the partially pure function rules...
On 25/04/2008, Yigal Chripun <yigal100 gmail.com> wrote:D2 will allow the following: pure invariant invariant(int) func(invariant(int)) nothrow; Am I the only one that thinks the above is too much?You're not the only one. Just for the record though, invariant(int) will implicitly cast to and from int, so the above could be simiplified to pure invariant int func(int) nothrow; However, the following cannot be simplified pure invariant invariant(C) func(invariant(C) c) nothrow; where C is a class. And it gets worse. Consider the following code: pure int func(invariant(C) a, invariant(C) b) { if (c == b) ... Whoops! That won't compile, because - guess what!? - opEquals isn't pure!!!! And it doesn't stop there - opEquals cannot be made pure just by changing its declaration, because a pure function must have invariant arguments, and opEquals has to work with or without invariant data. The upshot is that, eventually, Object.opEquals may have to be implemented twice: class Object { // the normal version const bool opEquals(const Object o) {...} // the pure version pure invariant bool opEquals(invariant Object o) {...} } and, therefore, so will anything that overloads it. And then there are delegates. I have mentioned in a previous thread (called something like "big hole in const system") that big problems exist because attributes can be applied to functions /but not to delegates/. That is, we cannot declare pure invariant invariant(C) delegate(invariant(C) c) nothrow dg; If we take the address of func, where func is declared as pure invariant invariant(C) func(invariant(C) c) nothrow; then &func will have type invariant(C) delegate(invariant(C)) That is, all the attributes will have been lost. That makes it possible to break any contract implied by the attributes without the compiler noticing, /just by taking the address of a function/. And then we come to templates. Oh my! These new attributes are going to cause a big problem for templates. Consider: ReturnType!(f) foo(alias f)(ParameterTypeTuple!(f) n) { return f(n); } or should that be... ReturnType!(f) foo(alias f)(ParameterTypeTuple!(f) n) nothrow { return f(n); } ? Hmm. Looks like the real answer is template foo(alias f) { if(is(f == nothrow)) { ReturnType!(f) foo(ParameterTypeTuple!(f) n) nothrow { return f(n); } } else { ReturnType!(f) foo(ParameterTypeTuple!(f) n) { return f(n); } } } (and even that's assuming that we will be able to test for "if(is(f == nothrow))", which also is not certain). In fact, really, the template should also test for "pure" as well, so it can attach the "pure" attribute if it can. And just in case anyone thinks that was a contrived example, real world uses would include root-solving by Newton's method, root-solving by the secant method, numerical integration, etc. - all of which will be pure iff f is pure, nothrow iff f is nothrow, etc. While I understand the reasons for "pure", etc. (- and don't misunderstand me, they are sound reasons!), there are implications for syntax which will come back and bite us if we're not careful. At the very least, I would suggest (1) attributes for delegates (2) attribute tuples for templates (e.g. AttributeTuple!(f) ReturnType!(f) foo(alias f)(ParameterTypeTuple!(f) n) { return f(n); } )
Apr 25 2008
Janice Caron wrote:While I understand the reasons for "pure", etc. (- and don't misunderstand me, they are sound reasons!), there are implications for syntax which will come back and bite us if we're not careful. At the very least, I would suggest (1) attributes for delegates (2) attribute tuples for templates (e.g. AttributeTuple!(f) ReturnType!(f) foo(alias f)(ParameterTypeTuple!(f) n) { return f(n); } )My example was a contrived one, but you provided good examples that illustrates the syntactic issues that arise from all those additions to D's syntax. One note regarding your template example: I don't see how that AttributeTuple!(f) helps. this should be solved via introspection at runtime or via traits at compile type. either way, it should be possible to get f's attributes in a tuple/array. something like: f.attributesof which would return a tuple of attributes. since I'm advocating for introduction of user defined attributes to D, I'd suggest that the compiler should treat "const"/"pure" and such as built-in attributes that are provided by the language, so that if you define: [myAttr1, myAttr2] pure int func(invariant C c); then func.attributesof would contain the tuple: (pure, myAttr1, myAttr2). just like a type tuple can contain both built-in types and user defined ones. --Yigal
Apr 25 2008
And then there are delegates. I have mentioned in a previous thread (called something like "big hole in const system") that big problems exist because attributes can be applied to functions /but not to delegates/. That is, we cannot declare pure invariant invariant(C) delegate(invariant(C) c) nothrow dg;For what it's worth, the D spec 2.013 allows delegates to have the pure and nothrow attributes. (Declarations: BasicType2 and Expressions: FunctionLiteral) Christian
Apr 25 2008
On 25/04/2008, Christian Kamm <kamm.incasoftware shift-at-left-and-remove-this.de> > > For what it's worth, the D spec 2.013 allows delegates to have the pure andnothrow attributes. (Declarations: BasicType2 and Expressions: FunctionLiteral)Ooh nice! Thanks for pointing that out. But they need to be able to take const and invariant attributes too. (And come to think of it, if you allowed delegates to be declared static then we could lose the "function" keyword altogether, as "delegate static" could take over that role. Maybe that's pushing things too far though).
Apr 25 2008
Janice Caron wrote:On 25/04/2008, Yigal Chripun <yigal100 gmail.com> wrote:I second that.D2 will allow the following: pure invariant invariant(int) func(invariant(int)) nothrow; Am I the only one that thinks the above is too much?You're not the only one.pure int func(invariant(C) a, invariant(C) b) { if (c == b) ... Whoops! That won't compile, because - guess what!? - opEquals isn't pure!!!! And it doesn't stop there - opEquals cannot be made pure just by changing its declaration, because a pure function must have invariant arguments, and opEquals has to work with or without invariant data. The upshot is that, eventually, Object.opEquals may have to be implemented twice: class Object { // the normal version const bool opEquals(const Object o) {...} // the pure version pure invariant bool opEquals(invariant Object o) {...} } and, therefore, so will anything that overloads it.Another example why "scoped const", despite "only" being a syntactical convenience, might be so important. -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Apr 29 2008
On 29/04/2008, Bruno Medeiros <brunodomedeiros+spam com.gmail> wrote:Another example why "scoped const", despite "only" being a syntactical convenience, might be so important.That wouldn't help in this case. The reason you need the second declaration is so that one declaration can be pure, the other not. Steven's proposal solves a different problem.
Apr 29 2008
Janice Caron wrote:On 29/04/2008, Bruno Medeiros <brunodomedeiros+spam com.gmail> wrote:Not if you combine "scoped const" with the partially pure function rules (see new thread). Example: //(using 'anyconst' as the scoped const keyword) class Object { pure anyconst bool opEquals(anyconst(Object) obj) {...} The 3 versions of opEquals would be created. 2 of them would partially pure, the other (the invariant one) would be fully pure. The mutable version would be redudant though. This would work, but since there is redundancy, I'm thinking there could be a better way to do it. -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DAnother example why "scoped const", despite "only" being a syntactical convenience, might be so important.That wouldn't help in this case. The reason you need the second declaration is so that one declaration can be pure, the other not. Steven's proposal solves a different problem.
Apr 29 2008