digitalmars.D - UFCS idea
- Alex_Dovhal (21/21) Jun 08 2011 There have been several topics discussing UFCS recently. So here is one
- Andrej Mitrovic (1/1) Jun 08 2011 @_ <- that's a snail.
- Alex_Dovhal (3/4) Jun 08 2011 thanks, i didn't knew that :)
- Dmitry Olshansky (8/29) Jun 08 2011 what was so bad about having 'this' inside parameters?
- Timon Gehr (5/10) Jun 08 2011 Furthermore, it should be illegal to make UFCS clash with a method's nam...
- Dmitry Olshansky (6/17) Jun 08 2011 Me thinks it should be counted as another overload, and be resolved in
- Timon Gehr (4/20) Jun 08 2011 How does that prevent hijacking? If you want it to overload against memb...
- Dmitry Olshansky (9/28) Jun 08 2011 Ehm, right in fact it seems that the function needs to participate in
- Alex_Dovhal (15/29) Jun 08 2011 Yes, but imagine you have a situation:
- Dmitry Olshansky (6/38) Jun 08 2011 well, and compiler tells him about ambiguity and for a good reason.
- Timon Gehr (3/16) Jun 08 2011 No, his 100 calls are all unambiguous.
- Dmitry Olshansky (11/28) Jun 08 2011 That, if we do rewrite in one direction only:
- Timon Gehr (6/33) Jun 08 2011 No. _That_ code would blow up during compilation because it is an ambigu...
- Alex_Dovhal (3/6) Jun 08 2011 Sorry I meant x.member3(1);
- Alex_Dovhal (9/18) Jun 08 2011 UFCS with 'this' is not bad. I've just got another competitive idea whic...
- Dmitry Olshansky (17/41) Jun 08 2011 Isn't this a main point of UFCS to have member syntax x.method(...) be
- Alex_Dovhal (2/13) Jun 08 2011 Agree.
- bearophile (5/10) Jun 08 2011 To solve such problems Haskell uses the $ operator (and the "." operator...
- Andrej Mitrovic (2/2) Jun 08 2011 Keep the language simple, why the verbosity with special symbols?
- bearophile (7/9) Jun 08 2011 My post was referring about two or three symbols. Regarding two of them,...
- Andrej Mitrovic (2/2) Jun 08 2011 I doubt a non-null reference is going to get its own symbol. It's
- Timon Gehr (27/41) Jun 08 2011 and . operators used in Haskell, they may look a bit weird for the first...
- David Nadlinger (11/13) Jun 08 2011 Nope, what's commonly meant by »non-nullable references« is, having so...
- Adam D. Ruppe (16/17) Jun 08 2011 I believe we're getting this in the library soon. I saw disabling
- Timon Gehr (4/18) Jun 08 2011 I understand that. I just think it would be a bit messy to have both @ r...
- Daniel Gibson (5/30) Jun 08 2011 I don't think it's for call by reference, it's to enforce that something
- Andrew Wiley (23/44) Jun 09 2011 I find it funny that @ was initially adopted for annotations, to be used
- Jonathan M Davis (13/66) Jun 09 2011 As it is, user-defined attributes can be added later using the @ syntax....
- Alex_Dovhal (5/17) Jun 09 2011 Thanks, Dmitry Olshansky has already explained why using "this" is fully...
- Andrew Wiley (14/88) Jun 09 2011 This is the difference in philosophy at the core of my general unhappine...
- Kagamin (2/6) Jun 09 2011 By "any other language" you must mean C# :)
- Andrew Wiley (2/10) Jun 09 2011 And Java/Scala.
- Jonathan M Davis (10/99) Jun 09 2011 I don't really see anything wrong with leaving the current @ attributes ...
- Andrew Wiley (5/119) Jun 09 2011 My point wasn't that the syntax should be different (it should definitel...
- Jonathan M Davis (9/160) Jun 09 2011 Well, adding user-defined attributes would be purely an additive change ...
There have been several topics discussing UFCS recently. So here is one more) One idea about UFCS - mark UFCS argument with , _, or _ symbol, e.g. you have some function: void func(Type1 p1, Type2 p2); and later call it: fucn(a, b); //or a.func( _, b); //or b.func(a, _); This way Timon Gehr's example: take(10,stride(2,cycle([3,2,5,3]))); [3,2,5,3].cycle().stride(2).take(10); would be written as this: [3,2,5,3].cycle( _).stride(2, _).take(10, _); Which is a little longer. On the other side this way benefits from: * UFCS is directly seen by both the programmer and compiler; * UFCS doesn't mix with member call syntax; * UFCS can be used for any type and for any argument, e.g. a.func( , b) or b.func(a, ); * UFCS can be used for more than one argument: a.func( _, _~[1]); What do you think?
Jun 08 2011
"Andrej Mitrovic" <andrej.mitrovich gmail.com> ???????/???????? ? ???????? ?????????: news:mailman.717.1307563594.14074.digitalmars-d puremagic.com..._ <- that's a snail.thanks, i didn't knew that :)
Jun 08 2011
On 08.06.2011 23:41, Alex_Dovhal wrote:There have been several topics discussing UFCS recently. So here is one more) One idea about UFCS - mark UFCS argument with , _, or _ symbol, e.g. you have some function: void func(Type1 p1, Type2 p2); and later call it: fucn(a, b); //or a.func( _, b); //or b.func(a, _); This way Timon Gehr's example: take(10,stride(2,cycle([3,2,5,3]))); [3,2,5,3].cycle().stride(2).take(10); would be written as this: [3,2,5,3].cycle( _).stride(2, _).take(10, _); Which is a little longer. On the other side this way benefits from: * UFCS is directly seen by both the programmer and compiler; * UFCS doesn't mix with member call syntax; * UFCS can be used for any type and for any argument, e.g. a.func( , b) or b.func(a, ); * UFCS can be used for more than one argument: a.func( _, _~[1]); What do you think?what was so bad about having 'this' inside parameters? I thought it was rather compelling: void func(Type1 this, Type2 p2); which is legal only as a free function and inside structs/classes it's declaration syntax error. [3,2,5,3].cycle.stride(2).take(10); //and no snails :) -- Dmitry Olshansky
Jun 08 2011
Dmitry Olshansky wrote:what was so bad about having 'this' inside parameters? I thought it was rather compelling: void func(Type1 this, Type2 p2); which is legal only as a free function and inside structs/classes it'sdeclaration syntax error.[3,2,5,3].cycle.stride(2).take(10); //and no snails :)Furthermore, it should be illegal to make UFCS clash with a method's name in order to prevent hijacking. Timon
Jun 08 2011
On 09.06.2011 0:39, Timon Gehr wrote:Dmitry Olshansky wrote:Me thinks it should be counted as another overload, and be resolved in the same way - partial ordering, and report ambiguity if can't choose one. Less special casing.what was so bad about having 'this' inside parameters? I thought it was rather compelling: void func(Type1 this, Type2 p2); which is legal only as a free function and inside structs/classes it'sdeclaration syntax error.[3,2,5,3].cycle.stride(2).take(10); //and no snails :)Furthermore, it should be illegal to make UFCS clash with a method's name in order to prevent hijacking.Timon-- Dmitry Olshansky
Jun 08 2011
Dmitry Olshansky wrote: On 09.06.2011 0:39, Timon Gehr wrote:How does that prevent hijacking? If you want it to overload against members of the same name, you would have to introduce another overload set, not just another overload. (But indeed, that would be more consistent.) TimonDmitry Olshansky wrote:Me thinks it should be counted as another overload, and be resolved in the same way - partial ordering, and report ambiguity if can't choose one. Less special casing.what was so bad about having 'this' inside parameters? I thought it was rather compelling: void func(Type1 this, Type2 p2); which is legal only as a free function and inside structs/classes it'sdeclaration syntax error.[3,2,5,3].cycle.stride(2).take(10); //and no snails :)Furthermore, it should be illegal to make UFCS clash with a method's name in order to prevent hijacking.Timon
Jun 08 2011
On 09.06.2011 0:48, Timon Gehr wrote:Ehm, right in fact it seems that the function needs to participate in two overload sets: first is used when it's called as member function, the set consists of all UFCS functions & member functions with the same name. second is used when it's called as free function, the set consists of all UFCS functions & free functions with the same name. -- Dmitry OlshanskyDmitry Olshansky wrote: On 09.06.2011 0:39, Timon Gehr wrote:How does that prevent hijacking? If you want it to overload against members of the same name, you would have to introduce another overload set, not just another overload. (But indeed, that would be more consistent.)Dmitry Olshansky wrote:Me thinks it should be counted as another overload, and be resolved in the same way - partial ordering, and report ambiguity if can't choose one. Less special casing.what was so bad about having 'this' inside parameters? I thought it was rather compelling: void func(Type1 this, Type2 p2); which is legal only as a free function and inside structs/classes it'sdeclaration syntax error.[3,2,5,3].cycle.stride(2).take(10); //and no snails :)Furthermore, it should be illegal to make UFCS clash with a method's name in order to prevent hijacking.Timon
Jun 08 2011
"Dmitry Olshansky" <dmitry.olsh gmail.com> ???????/???????? ? ???????? ?????????: news:isopbg$1l5d$1 digitalmars.com...Yes, but imagine you have a situation: someLib.d: class A{ void member1(int a); void member2(int a); ... } someUserCode.d: void member3(A this, int a); //local user func ... member3(x, 1); //hundred times in user code And later library writer adds void member3(int a) member to class A. Now user code has name collision.How does that prevent hijacking? If you want it to overload against members of the same name, you would have to introduce another overload set, not just another overload. (But indeed, that would be more consistent.)Ehm, right in fact it seems that the function needs to participate in two overload sets: first is used when it's called as member function, the set consists of all UFCS functions & member functions with the same name. second is used when it's called as free function, the set consists of all UFCS functions & free functions with the same name. -- Dmitry Olshansky
Jun 08 2011
On 09.06.2011 1:41, Alex_Dovhal wrote:"Dmitry Olshansky"<dmitry.olsh gmail.com> ???????/???????? ? ???????? ?????????: news:isopbg$1l5d$1 digitalmars.com...well, and compiler tells him about ambiguity and for a good reason. Since UFCS is exactly to allow it to behave like a method isn't it? It's not like UFCS will solve this kind of problem staying what it is. -- Dmitry OlshanskyYes, but imagine you have a situation: someLib.d: class A{ void member1(int a); void member2(int a); ... } someUserCode.d: void member3(A this, int a); //local user func .... member3(x, 1); //hundred times in user code And later library writer adds void member3(int a) member to class A. Now user code has name collision.How does that prevent hijacking? If you want it to overload against members of the same name, you would have to introduce another overload set, not just another overload. (But indeed, that would be more consistent.)Ehm, right in fact it seems that the function needs to participate in two overload sets: first is used when it's called as member function, the set consists of all UFCS functions& member functions with the same name. second is used when it's called as free function, the set consists of all UFCS functions& free functions with the same name. -- Dmitry Olshansky
Jun 08 2011
Alex Dovhal wrote:Yes, but imagine you have a situation: someLib.d: class A{ void member1(int a); void member2(int a); ... } someUserCode.d: void member3(A this, int a); //local user func ... member3(x, 1); //hundred times in user code And later library writer adds void member3(int a) member to class A. Now user code has name collision.No, his 100 calls are all unambiguous. Timon
Jun 08 2011
On 09.06.2011 1:55, Timon Gehr wrote:Alex Dovhal wrote:That, if we do rewrite in one direction only: e.g. x.member3(1) --> member3(x, 1); but it would be an unpleasant surprise in this case, suppose his 101th call looked like: x.member3(1) then after change it suddenly stops calling his code, and calls library code. And silently! So I think UFCS should work in both directions. -- Dmitry OlshanskyYes, but imagine you have a situation: someLib.d: class A{ void member1(int a); void member2(int a); ... } someUserCode.d: void member3(A this, int a); //local user func ... member3(x, 1); //hundred times in user code And later library writer adds void member3(int a) member to class A. Now user code has name collision.No, his 100 calls are all unambiguous.
Jun 08 2011
Dmitry Olshansky wrote:On 09.06.2011 1:55, Timon Gehr wrote:No. _That_ code would blow up during compilation because it is an ambiguous call. It's iust like the rest of D.Alex Dovhal wrote:That, if we do rewrite in one direction only: e.g. x.member3(1) --> member3(x, 1); but it would be an unpleasant surprise in this case, suppose his 101th call looked like: x.member3(1) then after change it suddenly stops calling his code, and calls library code. And silently!Yes, but imagine you have a situation: someLib.d: class A{ void member1(int a); void member2(int a); ... } someUserCode.d: void member3(A this, int a); //local user func ... member3(x, 1); //hundred times in user code And later library writer adds void member3(int a) member to class A. Now user code has name collision.No, his 100 calls are all unambiguous.So I think UFCS should work in both directions.I don't. I do not see any use case for the other direction. (and it would be really screwy anyways) Use UFCS if you want both to be valid. Timon
Jun 08 2011
"Alex_Dovhal" <alex_dovhal yahoo.com>wrote:... [snip]member3(x, 1); //hundred times in user code And later library writer adds void member3(int a) member to class A. Now user code has name collision.Sorry I meant x.member3(1);
Jun 08 2011
"Dmitry Olshansky" <dmitry.olsh gmail.com> wrotewhat was so bad about having 'this' inside parameters? I thought it was rather compelling: void func(Type1 this, Type2 p2); which is legal only as a free function and inside structs/classes it's declaration syntax error. [3,2,5,3].cycle.stride(2).take(10); //and no snails :) -- Dmitry OlshanskyUFCS with 'this' is not bad. I've just got another competitive idea which i'd like to discuss.[3,2,5,3].cycle.stride(2).take(10); //and no snails :)Yes, but can you tell what is stride(2) or take(10) - member function of UFCS? And which argument to it is one before dot? Sure here you can, but in more complex cases or when you don't want to strain you mind and memory. a.someUnknownToReaderFunc(b).otherNotOftenUsedFunc(c)
Jun 08 2011
On 09.06.2011 1:30, Alex_Dovhal wrote:"Dmitry Olshansky"<dmitry.olsh gmail.com> wroteIsn't this a main point of UFCS to have member syntax x.method(...) be substitute for method(x,...) ? :) Well, and to me having some freedom in position of this argument seems OK.what was so bad about having 'this' inside parameters? I thought it was rather compelling: void func(Type1 this, Type2 p2); which is legal only as a free function and inside structs/classes it's declaration syntax error. [3,2,5,3].cycle.stride(2).take(10); //and no snails :) -- Dmitry OlshanskyUFCS with 'this' is not bad. I've just got another competitive idea which i'd like to discuss.[3,2,5,3].cycle.stride(2).take(10); //and no snails :)Yes, but can you tell what is stride(2) or take(10) - member function of UFCS?And which argument to it is one before dot?obviously, the one author of cycle, stride, take etc. meant to be. Most likely the first ? ;) Clearly there is a potential to abuse, but you can abuse a whole lot of other features.Sure here you can, but in more complex cases or when you don't want to strain you mind and memory. a.someUnknownToReaderFunc(b).otherNotOftenUsedFunc(c)Generally they are known to reader - they are free functions (and even small subset of those) anyway, not some scary monsters from hell. And you'd have to strain your mind and memory to check docs anyway. And of course bad pick of position for this argument is clearly possible. It's good thing that it remains in control of library writer, not user. Thus combinations stay limited, as careful library writer is usually expected thing, as for user it's not exactly. -- Dmitry Olshansky
Jun 08 2011
"Dmitry Olshansky" <dmitry.olsh gmail.com> wrote:Agree.Sure here you can, but in more complex cases or when you don't want to strain you mind and memory. a.someUnknownToReaderFunc(b).otherNotOftenUsedFunc(c)Generally they are known to reader - they are free functions (and even small subset of those) anyway, not some scary monsters from hell. And you'd have to strain your mind and memory to check docs anyway. And of course bad pick of position for this argument is clearly possible. It's good thing that it remains in control of library writer, not user. Thus combinations stay limited, as careful library writer is usually expected thing, as for user it's not exactly.
Jun 08 2011
Alex_Dovhal:One idea about UFCS - mark UFCS argument with , _, or _ symbol, e.g. you have some function:Maybe it's better to save the prefix for a more important purpose: to tag reference/pointer types that can't be null.[3,2,5,3].cycle().stride(2).take(10); would be written as this: [3,2,5,3].cycle( _).stride(2, _).take(10, _);To solve such problems Haskell uses the $ operator (and the "." operator). What about adding the same *binary* operator to D? Bye, bearophile
Jun 08 2011
Keep the language simple, why the verbosity with special symbols? Leave that to Perl 7 fans.
Jun 08 2011
Andrej Mitrovic:Keep the language simple, why the verbosity with special symbols? Leave that to Perl 7 fans.My post was referring about two or three symbols. Regarding two of them, the $ and . operators used in Haskell, they may look a bit weird for the first hour your use Haskell, but after that you learn to appreciate them, and use them all the time, because they allow you to write very clean code. Haskell code is not easy to write for newbies, but it's easy enough to read. "Advanced" Haskell code uses several funny operators (like &&&, etc), but the basic ones like ++ and $ have a very simple semantics and you use them very often. So while Haskell is not an "easy" language, its code is more readable and quite more clean than Perl code. In Perl you use all kind of side effects, invisible variables, global variables, this doesn't happen in Haskell. So you can't compare the two languages. In the end an operator like $ is just syntax sugar, so it's not so important. The third symbol I was talking about was the used to denote reference/pointer types that can't be null (and ? used for the normal nullable ones). This is not just syntax sugar, this needs a change to the type system too. And I think it's a change important enough to deserve a special symbol in the language. Recently Andrei has said something is moving about this whole topic, so we'll see. So I agree it's generally better to avoid special symbols, but there are situations where they are acceptable, if their semantics is "natural" (like coming from mathematics), or if their usage is very common (like the $ . ++ in Haskell), or if they are important enough (like a symbol used to denote nullable/nonnullable reference type). Bye, bearophile
Jun 08 2011
I doubt a non-null reference is going to get its own symbol. It's probably going to get a new keyword. But that's just a hunch of mine.
Jun 08 2011
bearophile wrote:Andrej Mitrovic:and . operators used in Haskell, they may look a bit weird for the first hour your use Haskell, > but after that you learn to appreciate them, and use them all the time, because they allow you to write very clean code. Haskell code is not easy to write for newbies, butKeep the language simple, why the verbosity with special symbols? Leave that to Perl 7 fans.My post was referring about two or three symbols. Regarding two of them, the $it's easy enough to read. "Advanced" Haskell code uses several funny operators(like &&&, etc), but the basic ones like ++ and $ have a very simple semantics and you use themvery often. So while Haskell is not an "easy" language, its code is morereadable and quite more clean than Perl code. In Perl you use all kind of side effects, invisiblevariables, global variables, this doesn't happen in Haskell. So you can'tcompare the two languages.In the end an operator like $ is just syntax sugar, so it's not so important. The third symbol I was talking about was the used to denote reference/pointertypes that can't be null (and ? used for the normal nullable ones). This is not just syntaxsugar, this needs a change to the type system too. And I think it's a changeimportant enough to deserve a special symbol in the language. Recently Andrei has said somethingis moving about this whole topic, so we'll see. So I agree it's generally better to avoid special symbols, but there aresituations where they are acceptable, if their semantics is "natural" (like coming from mathematics), > or if their usage is very common (like the $ . ++ in Haskell), or if they are important enough (like a symbol used to denote nullable/nonnullable reference type).Bye, bearophileI'm very curious how you wold fit the $ operator into D. Afaik $ in haskell is just an infix operator for (partial) function application at a lower precedence? D does not have built in partial function application since all arguments are always passed in tuples so you'd have a hard time to make take 10 $ stride 2 $ cycle [1,2,3]; work in D. Also, don't we have non-nullable references in the language already?: int foo(ref int x){ // non nullable int reference! Timon
Jun 08 2011
On 6/9/11 2:10 AM, Timon Gehr wrote:Also, don't we have non-nullable references in the language already?: int foo(ref int x){ // non nullable int reference!Nope, what's commonly meant by »non-nullable references« is, having some reference type, the ability to declare some variable of that type that can never be null, i.e.: --- class Foo {} void main() { Foo foo; // An error, because foo would be null. } --- David
Jun 08 2011
Foo foo; // An error, because foo would be null.I believe we're getting this in the library soon. I saw disabling the default constructor on a todo list not long ago. By disabling the default constructor, a library construct will be able to reliably detect null at construction time: struct NotNull(T) { disable this() {} this(T t) { assert(t !is null); payload = t; } T payload; alias payload this; } NotNull!(int*) a; // error - default constructor is disabled int* aPtr = null; auto a = NotNull(aPtr); // assert triggers at runtime - a is never null The type system may or may not catch nulls - depends on the specific implementation of the struct - but worst case, it will be noticed immediately at runtime when you try to store it.
Jun 08 2011
David Nadlinger wrote:On 6/9/11 2:10 AM, Timon Gehr wrote:I understand that. I just think it would be a bit messy to have both references and ref for call by reference. TimonAlso, don't we have non-nullable references in the language already?: int foo(ref int x){ // non nullable int reference!Nope, what's commonly meant by »non-nullable references« is, having some reference type, the ability to declare some variable of that type that can never be null, i.e.: --- class Foo {} void main() { Foo foo; // An error, because foo would be null. } --- David
Jun 08 2011
Am 09.06.2011 02:32, schrieb Timon Gehr:David Nadlinger wrote:I don't think it's for call by reference, it's to enforce that something that already is a reference type (Objects, pointers) are not null. Cheers, - DanielOn 6/9/11 2:10 AM, Timon Gehr wrote:I understand that. I just think it would be a bit messy to have both references and ref for call by reference. TimonAlso, don't we have non-nullable references in the language already?: int foo(ref int x){ // non nullable int reference!Nope, what's commonly meant by »non-nullable references« is, having some reference type, the ability to declare some variable of that type that can never be null, i.e.: --- class Foo {} void main() { Foo foo; // An error, because foo would be null. } --- David
Jun 08 2011
On Wed, Jun 8, 2011 at 12:41 PM, Alex_Dovhal <alex_dovhal yahoo.com> wrote:There have been several topics discussing UFCS recently. So here is one more) One idea about UFCS - mark UFCS argument with , _, or _ symbol, e.g. you have some function: void func(Type1 p1, Type2 p2); and later call it: fucn(a, b); //or a.func( _, b); //or b.func(a, _); This way Timon Gehr's example: take(10,stride(2,cycle([3,2,5,3]))); [3,2,5,3].cycle().stride(2).take(10); would be written as this: [3,2,5,3].cycle( _).stride(2, _).take(10, _); Which is a little longer. On the other side this way benefits from: * UFCS is directly seen by both the programmer and compiler; * UFCS doesn't mix with member call syntax; * UFCS can be used for any type and for any argument, e.g. a.func( , b) or b.func(a, ); * UFCS can be used for more than one argument: a.func( _, _~[1]); What do you think?I find it funny that was initially adopted for annotations, to be used similar to Java and Scala. I come from that world, and one of the rules for annotations is that they cannot directly alter the code the compiler outputs. You can add plugins to the Java compiler that use annotations to modify the AST before it's compiled, and you can use annotations for runtime bytecode generation or interpret them using reflection, but if you take unannotated code and annotated code and compile it (without altering the compiler), the generated code will not change. The idea was to make them a part of the language composed entirely of metadata (some of which was enforced to be correct by the compiler) that could be completely ignored if the programmer didn't want to use it. Now that D has taken up this syntax, we've done almost the opposite. is mostly used in situations where it changes the compiled code, changes the existing language, and is in no way optional. We don't really support user defined metadata, and we can't use what annotations we have as metadata because only the compiler can actually use it. Most of the uses I've seen seem to be a way to cram more keywords into the language without adding more keywords. I've been holding in this sort of rant for a while, but in summary, my response is that unless the desired use for was defined radically differently by D when it was adopted (and, as far as I can tell, it wasn't), seeing another abuse of it just makes me feel slightly sick inside.
Jun 09 2011
On 2011-06-09 00:20, Andrew Wiley wrote:On Wed, Jun 8, 2011 at 12:41 PM, Alex_Dovhal <alex_dovhal yahoo.com> wrote:As it is, user-defined attributes can be added later using the syntax. True, all of the current uses of are for where we decided to save a keyword, but that doesn't stop user-defined attributes from using the syntax later. It just means that those that are currently defined will always be special. Regardless, I see little point in using it for UFCS. If we want to specifically mark parameters for it, I think that the suggestion of using "this" makes a lot more sense. You wouldn't even have to change the grammar (unlike if you used ). You'd just change the semantic phase to treat "this" specially as a function parameter and not freak out about it being a keyword. Using would be a much bigger language change and for no gain whatsoever as far as I can see. - Jonathan M DavisThere have been several topics discussing UFCS recently. So here is one more) One idea about UFCS - mark UFCS argument with , _, or _ symbol, e.g. you have some function: void func(Type1 p1, Type2 p2); and later call it: fucn(a, b); //or a.func( _, b); //or b.func(a, _); This way Timon Gehr's example: take(10,stride(2,cycle([3,2,5,3]))); [3,2,5,3].cycle().stride(2).take(10); would be written as this: [3,2,5,3].cycle( _).stride(2, _).take(10, _); Which is a little longer. On the other side this way benefits from: * UFCS is directly seen by both the programmer and compiler; * UFCS doesn't mix with member call syntax; * UFCS can be used for any type and for any argument, e.g. a.func( , b) or b.func(a, ); * UFCS can be used for more than one argument: a.func( _, _~[1]); What do you think?I find it funny that was initially adopted for annotations, to be used similar to Java and Scala. I come from that world, and one of the rules for annotations is that they cannot directly alter the code the compiler outputs. You can add plugins to the Java compiler that use annotations to modify the AST before it's compiled, and you can use annotations for runtime bytecode generation or interpret them using reflection, but if you take unannotated code and annotated code and compile it (without altering the compiler), the generated code will not change. The idea was to make them a part of the language composed entirely of metadata (some of which was enforced to be correct by the compiler) that could be completely ignored if the programmer didn't want to use it. Now that D has taken up this syntax, we've done almost the opposite. is mostly used in situations where it changes the compiled code, changes the existing language, and is in no way optional. We don't really support user defined metadata, and we can't use what annotations we have as metadata because only the compiler can actually use it. Most of the uses I've seen seem to be a way to cram more keywords into the language without adding more keywords. I've been holding in this sort of rant for a while, but in summary, my response is that unless the desired use for was defined radically differently by D when it was adopted (and, as far as I can tell, it wasn't), seeing another abuse of it just makes me feel slightly sick inside.
Jun 09 2011
"Jonathan M Davis" <jmdavisProg gmx.com> wote:Regardless, I see little point in using it for UFCS. If we want to specifically mark parameters for it, I think that the suggestion of using "this" makes a lot more sense. You wouldn't even have to change the grammar (unlike if you used ). You'd just change the semantic phase to treat "this" specially as a function parameter and not freak out about it being a keyword. Using would be a much bigger language change and for no gain whatsoever as far as I can see. - Jonathan M DavisThanks, Dmitry Olshansky has already explained why using "this" is fully suitable. One thing I personally dislike in UFCS is that it's impossible to visually separate it from member call syntax, only by context. But this is only personal taste. Sorry for noise.
Jun 09 2011
On Thu, Jun 9, 2011 at 12:46 AM, Jonathan M Davis <jmdavisProg gmx.com>wrote:On 2011-06-09 00:20, Andrew Wiley wrote:This is the difference in philosophy at the core of my general unhappiness. When Java officially added annotations, they were designed and built to be used for user-defined metadata. We added "Property" to the grammar, celebrated that we had them too, then stopped. The result is that we're throwing around as an excuse for language keywords and boasting about how we have annotations when, by the definition of any other language, we simply don't. I guess the best answer from where I'm standing is to start throwing around possible syntaxes for annotation declarations and references to them in compile-time reflection. I just really hope this gets in to D2, so we aren't permanently stuck with "fake annotations." Regardless, I see little point in using it for UFCS. If we want toOn Wed, Jun 8, 2011 at 12:41 PM, Alex_Dovhal <alex_dovhal yahoo.com>wrote:forThere have been several topics discussing UFCS recently. So here is one more) One idea about UFCS - mark UFCS argument with , _, or _ symbol, e.g. you have some function: void func(Type1 p1, Type2 p2); and later call it: fucn(a, b); //or a.func( _, b); //or b.func(a, _); This way Timon Gehr's example: take(10,stride(2,cycle([3,2,5,3]))); [3,2,5,3].cycle().stride(2).take(10); would be written as this: [3,2,5,3].cycle( _).stride(2, _).take(10, _); Which is a little longer. On the other side this way benefits from: * UFCS is directly seen by both the programmer and compiler; * UFCS doesn't mix with member call syntax; * UFCS can be used for any type and for any argument, e.g. a.func( , b) or b.func(a, ); * UFCS can be used for more than one argument: a.func( _, _~[1]); What do you think?I find it funny that was initially adopted for annotations, to be used similar to Java and Scala. I come from that world, and one of the rulesannotations is that they cannot directly alter the code the compiler outputs. You can add plugins to the Java compiler that use annotations to modify the AST before it's compiled, and you can use annotations for runtime bytecode generation or interpret them using reflection, but ifyoutake unannotated code and annotated code and compile it (without altering the compiler), the generated code will not change. The idea was to make them a part of the language composed entirely of metadata (some of which was enforced to be correct by the compiler) that could be completely ignored if the programmer didn't want to use it. Now that D has taken up this syntax, we've done almost the opposite. is mostly used in situations where it changes the compiled code, changes the existing language, and is in no way optional. We don't really supportuserdefined metadata, and we can't use what annotations we have as metadata because only the compiler can actually use it. Most of the uses I've seen seem to be a way to cram more keywords into the language without adding more keywords. I've been holding in this sort of rant for a while, but in summary, my response is that unless the desired use for was defined radically differently by D when it was adopted (and, as far as I can tell, it wasn't), seeing another abuse of it just makes me feel slightly sick inside.As it is, user-defined attributes can be added later using the syntax. True, all of the current uses of are for where we decided to save a keyword, but that doesn't stop user-defined attributes from using the syntax later. It just means that those that are currently defined will always be special.specifically mark parameters for it, I think that the suggestion of using "this" makes a lot more sense. You wouldn't even have to change the grammar (unlike if you used ). You'd just change the semantic phase to treat "this" specially as a function parameter and not freak out about it being a keyword. Using would be a much bigger language change and for no gain whatsoever as far as I can see.I agree. The "this" syntax seems far more logical and straightforward.
Jun 09 2011
Andrew Wiley Wrote:celebrated that we had them too, then stopped. The result is that we're throwing around as an excuse for language keywords and boasting about how we have annotations when, by the definition of any other language, we simply don't.
Jun 09 2011
On Thu, Jun 9, 2011 at 4:29 AM, Kagamin <spam here.lot> wrote:Andrew Wiley Wrote:And Java/Scala.celebrated that we had them too, then stopped. The result is that we're throwing around as an excuse for language keywords and boasting abouthowwe have annotations when, by the definition of any other language, wesimplydon't.
Jun 09 2011
On 2011-06-09 01:15, Andrew Wiley wrote:On Thu, Jun 9, 2011 at 12:46 AM, Jonathan M Davis<jmdavisProg gmx.com>wrote:I don't really see anything wrong with leaving the current attributes as they are and then just using for user-defined attributes as well. There will just be a set of attribute names which are reserved by the compiler. All that using a different syntax for user-defined attributes would buy you would be that you could use the attribute names that the compiler has reserved - safe, trusted, system, and property. And that isn't exactly a huge gain. We might as well just use for user-defined attributes as well. - Jonathan M DavisOn 2011-06-09 00:20, Andrew Wiley wrote:This is the difference in philosophy at the core of my general unhappiness. When Java officially added annotations, they were designed and built to be used for user-defined metadata. We added "Property" to the grammar, celebrated that we had them too, then stopped. The result is that we're throwing around as an excuse for language keywords and boasting about how we have annotations when, by the definition of any other language, we simply don't. I guess the best answer from where I'm standing is to start throwing around possible syntaxes for annotation declarations and references to them in compile-time reflection. I just really hope this gets in to D2, so we aren't permanently stuck with "fake annotations."On Wed, Jun 8, 2011 at 12:41 PM, Alex_Dovhal <alex_dovhal yahoo.com>wrote:forThere have been several topics discussing UFCS recently. So here is one more) One idea about UFCS - mark UFCS argument with , _, or _ symbol, e.g. you have some function: void func(Type1 p1, Type2 p2); and later call it: fucn(a, b); //or a.func( _, b); //or b.func(a, _); This way Timon Gehr's example: take(10,stride(2,cycle([3,2,5,3]))); [3,2,5,3].cycle().stride(2).take(10); would be written as this: [3,2,5,3].cycle( _).stride(2, _).take(10, _); Which is a little longer. On the other side this way benefits from: * UFCS is directly seen by both the programmer and compiler; * UFCS doesn't mix with member call syntax; * UFCS can be used for any type and for any argument, e.g. a.func( , b) or b.func(a, ); * UFCS can be used for more than one argument: a.func( _, _~[1]); What do you think?I find it funny that was initially adopted for annotations, to be used similar to Java and Scala. I come from that world, and one of the rulesannotations is that they cannot directly alter the code the compiler outputs. You can add plugins to the Java compiler that use annotations to modify the AST before it's compiled, and you can use annotations for runtime bytecode generation or interpret them using reflection, but ifyoutake unannotated code and annotated code and compile it (without altering the compiler), the generated code will not change. The idea was to make them a part of the language composed entirely of metadata (some of which was enforced to be correct by the compiler) that could be completely ignored if the programmer didn't want to use it. Now that D has taken up this syntax, we've done almost the opposite. is mostly used in situations where it changes the compiled code, changes the existing language, and is in no way optional. We don't really supportuserdefined metadata, and we can't use what annotations we have as metadata because only the compiler can actually use it. Most of the uses I've seen seem to be a way to cram more keywords into the language without adding more keywords. I've been holding in this sort of rant for a while, but in summary, my response is that unless the desired use for was defined radically differently by D when it was adopted (and, as far as I can tell, it wasn't), seeing another abuse of it just makes me feel slightly sick inside.As it is, user-defined attributes can be added later using the syntax. True, all of the current uses of are for where we decided to save a keyword, but that doesn't stop user-defined attributes from using the syntax later. It just means that those that are currently defined will always be special.
Jun 09 2011
On Thu, Jun 9, 2011 at 1:32 AM, Jonathan M Davis <jmdavisProg gmx.com>wrote:On 2011-06-09 01:15, Andrew Wiley wrote:My point wasn't that the syntax should be different (it should definitely be the same), my point was that we stopped short of fully implementing annotation support and that the result seems to be significantly less than ideal.On Thu, Jun 9, 2011 at 12:46 AM, Jonathan M Davis<jmdavisProg gmx.com>wrote:theOn 2011-06-09 00:20, Andrew Wiley wrote:On Wed, Jun 8, 2011 at 12:41 PM, Alex_Dovhal <alex_dovhal yahoo.com>wrote:There have been several topics discussing UFCS recently. So here is one more) One idea about UFCS - mark UFCS argument with , _, or _ symbol, e.g. you have some function: void func(Type1 p1, Type2 p2); and later call it: fucn(a, b); //or a.func( _, b); //or b.func(a, _); This way Timon Gehr's example: take(10,stride(2,cycle([3,2,5,3]))); [3,2,5,3].cycle().stride(2).take(10); would be written as this: [3,2,5,3].cycle( _).stride(2, _).take(10, _); Which is a little longer. On the other side this way benefits from: * UFCS is directly seen by both the programmer and compiler; * UFCS doesn't mix with member call syntax; * UFCS can be used for any type and for any argument, e.g. a.func( , b) or b.func(a, ); * UFCS can be used for more than one argument: a.func( _, _~[1]); What do you think?I find it funny that was initially adopted for annotations, to be used similar to Java and Scala. I come from that world, and one ofannotationsrulesforannotations is that they cannot directly alter the code the compiler outputs. You can add plugins to the Java compiler that usecompiledto modify the AST before it's compiled, and you can use annotations for runtime bytecode generation or interpret them using reflection, but ifyoutake unannotated code and annotated code and compile it (without altering the compiler), the generated code will not change. The idea was to make them a part of the language composed entirely of metadata (some of which was enforced to be correct by the compiler) that could be completely ignored if the programmer didn't want to use it. Now that D has taken up this syntax, we've done almost the opposite. is mostly used in situations where it changes themetadatacode, changes the existing language, and is in no way optional. We don't really supportuserdefined metadata, and we can't use what annotations we have asmybecause only the compiler can actually use it. Most of the uses I've seen seem to be a way to cram more keywords into the language without adding more keywords. I've been holding in this sort of rant for a while, but in summary,syntax.response is that unless the desired use for was defined radically differently by D when it was adopted (and, as far as I can tell, it wasn't), seeing another abuse of it just makes me feel slightly sick inside.As it is, user-defined attributes can be added later using thekeyword,True, all of the current uses of are for where we decided to save aItbut that doesn't stop user-defined attributes from using the syntax later.unhappiness.just means that those that are currently defined will always be special.This is the difference in philosophy at the core of my generalWhen Java officially added annotations, they were designed and built tobeused for user-defined metadata. We added "Property" to the grammar, celebrated that we had them too, then stopped. The result is that we're throwing around as an excuse for language keywords and boasting abouthowwe have annotations when, by the definition of any other language, we simply don't. I guess the best answer from where I'm standing is to start throwingaroundpossible syntaxes for annotation declarations and references to them in compile-time reflection. I just really hope this gets in to D2, so we aren't permanently stuck with "fake annotations."I don't really see anything wrong with leaving the current attributes as they are and then just using for user-defined attributes as well. There will just be a set of attribute names which are reserved by the compiler. All that using a different syntax for user-defined attributes would buy you would be that you could use the attribute names that the compiler has reserved - safe, trusted, system, and property. And that isn't exactly a huge gain. We might as well just use for user-defined attributes as well.
Jun 09 2011
On 2011-06-09 12:01, Andrew Wiley wrote:On Thu, Jun 9, 2011 at 1:32 AM, Jonathan M Davis <jmdavisProg gmx.com>wrote:from:On 2011-06-09 01:15, Andrew Wiley wrote:On Thu, Jun 9, 2011 at 12:46 AM, Jonathan M Davis<jmdavisProg gmx.com>wrote:On 2011-06-09 00:20, Andrew Wiley wrote:On Wed, Jun 8, 2011 at 12:41 PM, Alex_Dovhal <alex_dovhal yahoo.com>wrote:There have been several topics discussing UFCS recently. So here is one more) One idea about UFCS - mark UFCS argument with , _, or _ symbol, e.g. you have some function: void func(Type1 p1, Type2 p2); and later call it: fucn(a, b); //or a.func( _, b); //or b.func(a, _); This way Timon Gehr's example: take(10,stride(2,cycle([3,2,5,3]))); [3,2,5,3].cycle().stride(2).take(10); would be written as this: [3,2,5,3].cycle( _).stride(2, _).take(10, _); Which is a little longer. On the other side this way benefitsWell, adding user-defined attributes would be purely an additive change and wouldn't break any code, so there's probably a decent chance that we'll be able to get it added to D2 at some point. But there are still plenty of more core issues that need to be addressed before we look at adding features like that, so I don't think that it's all that big a deal that we don't have them yet. I think that there's a good chance that we will eventually. - Jonathan M DavisMy point wasn't that the syntax should be different (it should definitely be the same), my point was that we stopped short of fully implementing annotation support and that the result seems to be significantly less than ideal.the* UFCS is directly seen by both the programmer and compiler; * UFCS doesn't mix with member call syntax; * UFCS can be used for any type and for any argument, e.g. a.func( , b) or b.func(a, ); * UFCS can be used for more than one argument: a.func( _, _~[1]); What do you think?I find it funny that was initially adopted for annotations, to be used similar to Java and Scala. I come from that world, and one ofannotationsrulesforannotations is that they cannot directly alter the code the compiler outputs. You can add plugins to the Java compiler that usecompiledto modify the AST before it's compiled, and you can use annotations for runtime bytecode generation or interpret them using reflection, but ifyoutake unannotated code and annotated code and compile it (without altering the compiler), the generated code will not change. The idea was to make them a part of the language composed entirely of metadata (some of which was enforced to be correct by the compiler) that could be completely ignored if the programmer didn't want to use it. Now that D has taken up this syntax, we've done almost the opposite. is mostly used in situations where it changes themetadatacode, changes the existing language, and is in no way optional. We don't really supportuserdefined metadata, and we can't use what annotations we have asmybecause only the compiler can actually use it. Most of the uses I've seen seem to be a way to cram more keywords into the language without adding more keywords. I've been holding in this sort of rant for a while, but in summary,syntax.response is that unless the desired use for was defined radically differently by D when it was adopted (and, as far as I can tell, it wasn't), seeing another abuse of it just makes me feel slightly sick inside.As it is, user-defined attributes can be added later using thekeyword,True, all of the current uses of are for where we decided to save aItbut that doesn't stop user-defined attributes from using the syntax later.unhappiness.just means that those that are currently defined will always be special.This is the difference in philosophy at the core of my generalWhen Java officially added annotations, they were designed and built tobeused for user-defined metadata. We added "Property" to the grammar, celebrated that we had them too, then stopped. The result is that we're throwing around as an excuse for language keywords and boasting abouthowwe have annotations when, by the definition of any other language, we simply don't. I guess the best answer from where I'm standing is to start throwingaroundpossible syntaxes for annotation declarations and references to them in compile-time reflection. I just really hope this gets in to D2, so we aren't permanently stuck with "fake annotations."I don't really see anything wrong with leaving the current attributes as they are and then just using for user-defined attributes as well. There will just be a set of attribute names which are reserved by the compiler. All that using a different syntax for user-defined attributes would buy you would be that you could use the attribute names that the compiler has reserved - safe, trusted, system, and property. And that isn't exactly a huge gain. We might as well just use for user-defined attributes as well.
Jun 09 2011