digitalmars.D - class extensions
- Michael Deardeuff (30/30) Aug 29 2007 I am very excited about the future of D. Walter's and Andrei's talk at t...
- Robert Fraser (30/69) Aug 29 2007 I proposed this a while ago, and I agree this would be a good idea. Howe...
- Michael Deardeuff (6/52) Aug 29 2007 Excellent point. Blast.
- kris (7/16) Aug 29 2007 Yeah, the proposed extensions raised all kinds of red flags for me at
- Bill Baxter (11/39) Aug 29 2007 It's pretty much the same deal as with property syntax. A lot of folks
- Downs (17/26) Aug 29 2007 -----BEGIN PGP SIGNED MESSAGE-----
- Alexander Panek (4/10) Aug 30 2007 Oooh it looks like this would be possible to write:
- Chris Nicholson-Sauls (5/18) Aug 30 2007 I reiterate what I've said about three times now: I watch as D slowly tu...
- Alexander Panek (15/20) Aug 30 2007 Hehe. They indeed have similarities - maybe not in language theory or
- Chris Nicholson-Sauls (10/34) Aug 30 2007 I'm sure we'll never, ever, see something quite like:
- Lutger (7/14) Aug 29 2007 What are the objections to this? Are there technical pitfalls?
- kris (36/51) Aug 29 2007 Technical? Since when did that become important? ;)
- Jarrett Billingsley (4/6) Aug 29 2007 I think by call-chaining he was referring to cases such as
- kris (2/9) Aug 29 2007 Had completely missed that, Jarret. Thanks, and fair point
- Lars Ivar Igesund (11/29) Aug 30 2007 It will also be directly detrimental to maintainability when used for us...
- Alexander Panek (8/14) Aug 30 2007 Well, usually a simple change to the import list will reveal where each
- Lars Ivar Igesund (12/28) Aug 30 2007 I probably miss your point here, but it certainly shouldn't be necessary...
- Alexander Panek (8/27) Aug 30 2007 On the other hand, the ambiguity problem:
- janderson (3/35) Aug 31 2007 Perhaps, but even without interchangeability warning signs go up for me
- Lutger (20/45) Aug 30 2007 I agree, although I am that enthusiast. The main reason I liked this
- Bill Baxter (31/38) Aug 30 2007 Namespace issues are why I don't currently find much use for the array
- Brad Roberts (7/42) Aug 30 2007 Don't overlook the changes upcoming in 2.0 to the overload resolution
- Bill Baxter (6/48) Aug 30 2007 Yeh, that should help some. But that doesn't seem to do anything about
- kris (2/47) Aug 30 2007 Amen
- Chris Nicholson-Sauls (18/57) Aug 30 2007 Or just use selective import to do the same thing:
- Bill Baxter (6/31) Aug 30 2007 Maybe even just use a semi-colon instead of comma in the arg list?
- Nathan Reed (5/35) Aug 30 2007 I like that syntax; something similiar is used in mathematics on
- Chris Nicholson-Sauls (5/42) Aug 30 2007 Agreed. I believe the use of semicolons within params was once suggeste...
- janderson (6/45) Aug 31 2007 I'm on the camp that like the interchangeable method/function syntax
- janderson (6/56) Aug 31 2007 Here's a thought.
I am very excited about the future of D. Walter's and Andrei's talk at the conference was awesome. However, there are still a few quirks to get out: This is regarding slide 9 of the presentation. I noticed that most people at the conference liked the idea of extending library classes, but were not to pleased with the interchangability of --- foo(a, args) --- and --- a.foo(args) --- like the arrays have. ---- class A {...} ... extension class A { void foo(args) {...} } ... a.foo(args); ---- (maybe the syntax could be "class extension A" or "extension A"...) In this way class extensions are clearly marked and the syntax is consistent. It would be easy to add interfaces to the library class: extension A : Visitable { void accept(Visitor v) {...} } Just an idea for you guys, Walter, Andrei, and the community. --Michael Deardeuff
Aug 29 2007
Michael Deardeuff Wrote:I am very excited about the future of D. Walter's and Andrei's talk at the conference was awesome. However, there are still a few quirks to get out: This is regarding slide 9 of the presentation. I noticed that most people at the conference liked the idea of extending library classes, but were not to pleased with the interchangability of --- foo(a, args) --- and --- a.foo(args) --- like the arrays have.Really? I got the feeling it was very well-received. I like the idea quite a bit, not necessarily just for class extensions (I think it might encourage a lower degree of encapsulation, although if the fields are package-private this might be mitigated by adding class extensions in other modules in the same package), but for primitive types.---- class A {...} ... extension class A { void foo(args) {...} } ... a.foo(args); ---- (maybe the syntax could be "class extension A" or "extension A"...) In this way class extensions are clearly marked and the syntax is consistent. It would be easy to add interfaces to the library class: extension A : Visitable { void accept(Visitor v) {...} } Just an idea for you guys, Walter, Andrei, and the community. --Michael DeardeuffI proposed this a while ago, and I agree this would be a good idea. However, the more I think about it, the more I realize that in a native-compiled language we're talking vtable problems - how do we know when the vtable is finished? If partials are cross-module, it would require recompilation of every involved module, and just be generally problematic. The suggestion that cam eup in the other thread was to use templates: --- interface IFoo { int bar(); } template IFoo_Impl() { int bar() { return 3; } } interface IBaz { string quux(); } template IBaz_Impl() { string quux() { return "abc"; } } class Baz : IFoo, IBaz { mixin IFoo_Impl!(); mixin IBaz_Impl(); } ---
Aug 29 2007
Robert Fraser Wrote:Michael Deardeuff Wrote:Excellent point. Blast. I think it still _is_ a good idea if you scrap the inheritance/vtable problem and only allow extension classes to use the syntax "a.foo(...);" I guess what I'm getting at is, I don't like the prospect of working with code that in one line is "foo(a, ...);" and the next "a.foo(...);" With the extension class bit it makes it clear that only methods meant as a class extension can (and must) use the "a.foo();" syntax, which I prefer. And, of course, I'm in here for myself. j/k. But not really. --Michael DeardeuffI am very excited about the future of D. Walter's and Andrei's talk at the conference was awesome. However, there are still a few quirks to get out: This is regarding slide 9 of the presentation. I noticed that most people at the conference liked the idea of extending library classes, but were not to pleased with the interchangability of --- foo(a, args) --- and --- a.foo(args) --- like the arrays have.Really? I got the feeling it was very well-received. I like the idea quite a bit, not necessarily just for class extensions (I think it might encourage a lower degree of encapsulation, although if the fields are package-private this might be mitigated by adding class extensions in other modules in the same package), but for primitive types.---- class A {...} ... extension class A { void foo(args) {...} } ... a.foo(args); ---- (maybe the syntax could be "class extension A" or "extension A"...) In this way class extensions are clearly marked and the syntax is consistent. It would be easy to add interfaces to the library class: extension A : Visitable { void accept(Visitor v) {...} } Just an idea for you guys, Walter, Andrei, and the community. --Michael DeardeuffI proposed this a while ago, and I agree this would be a good idea. However, the more I think about it, the more I realize that in a native-compiled language we're talking vtable problems - how do we know when the vtable is finished? If partials are cross-module, it would require recompilation of every involved module, and just be generally problematic.
Aug 29 2007
Michael Deardeuff wrote:Robert Fraser Wrote:[snip]Yeah, the proposed extensions raised all kinds of red flags for me at the conference. Bluntly, it felt like the notion of "structured programming" was being tossed out in favor of "slapdash programming" ... a brand new paradigm to go along with the other(s) being adopted :)I proposed this a while ago, and I agree this would be a good idea. However, the more I think about it, the more I realize that in a native-compiled language we're talking vtable problems - how do we know when the vtable is finished? If partials are cross-module, it would require recompilation of every involved module, and just be generally problematic.Excellent point. Blast. I think it still _is_ a good idea if you scrap the inheritance/vtable problem and only allow extension classes to use the syntax "a.foo(...);" I guess what I'm getting at is, I don't like the prospect of working with code that in one line is "foo(a, ...);" and the next "a.foo(...);" With the extension class bit it makes it clear that only methods meant as a class extension can (and must) use the "a.foo();" syntax, which I prefer. And, of course, I'm in here for myself. j/k. But not really. --Michael Deardeuff
Aug 29 2007
kris wrote:Michael Deardeuff wrote:It's pretty much the same deal as with property syntax. A lot of folks think the use of property syntax with a function should need to be enabled explicilty to avoid nonsense like writefln = 5; But Walter seems to think it's ok the way it is. Given that, I can definitely see how he'd think making a.foo uniformly interchangable with foo(a) makes sense. I guess with property syntax and this combined we'll have "a.value" == "value(a)" == "value = a" Which seems pretty weird to me. --bbRobert Fraser Wrote:[snip]Yeah, the proposed extensions raised all kinds of red flags for me at the conference. Bluntly, it felt like the notion of "structured programming" was being tossed out in favor of "slapdash programming" ... a brand new paradigm to go along with the other(s) being adopted :)I proposed this a while ago, and I agree this would be a good idea. However, the more I think about it, the more I realize that in a native-compiled language we're talking vtable problems - how do we know when the vtable is finished? If partials are cross-module, it would require recompilation of every involved module, and just be generally problematic.Excellent point. Blast. I think it still _is_ a good idea if you scrap the inheritance/vtable problem and only allow extension classes to use the syntax "a.foo(...);" I guess what I'm getting at is, I don't like the prospect of working with code that in one line is "foo(a, ...);" and the next "a.foo(...);" With the extension class bit it makes it clear that only methods meant as a class extension can (and must) use the "a.foo();" syntax, which I prefer. And, of course, I'm in here for myself. j/k. But not really. --Michael Deardeuff
Aug 29 2007
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Bill Baxter wrote:But Walter seems to think it's ok the way it is. Given that, I can definitely see how he'd think making a.foo uniformly interchangable with foo(a) makes sense. I guess with property syntax and this combined we'll have "a.value" == "value(a)" == "value = a" Which seems pretty weird to me. --bbI actually welcome this as a straightforward way to enable coders to write out what they mean. Of course, it can be abused for stuff like writefln="whee", but in many cases, abusability is related to the power/expressiveness of a feature - if you can use it to express more, it follows that you can also use it to express more garbage; however, that doesn't mean you have to. --downs -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFG1dBQpEPJRr05fBERAvSWAJ9oE3i7jIcSRnuiXVfFCz+SgFCARACfQTse ax7kN3DRe9CdOeC+ac+ihbE= =abAO -----END PGP SIGNATURE-----
Aug 29 2007
Bill Baxter wrote:[...] But Walter seems to think it's ok the way it is. Given that, I can definitely see how he'd think making a.foo uniformly interchangable with foo(a) makes sense. I guess with property syntax and this combined we'll have "a.value" == "value(a)" == "value = a"Oooh it looks like this would be possible to write: 3.times = (int a) { Stdout(a.toUtf8).newline; } ...fun! :D
Aug 30 2007
Alexander Panek wrote:Bill Baxter wrote:I reiterate what I've said about three times now: I watch as D slowly turns into Ruby. :) (Although I actually like pseudo-members. ColdC has this as well, but by modifying a type-lib object; $String.foo() callable as "abc".foo() for example.) -- Chris Nicholson-Sauls[...] But Walter seems to think it's ok the way it is. Given that, I can definitely see how he'd think making a.foo uniformly interchangable with foo(a) makes sense. I guess with property syntax and this combined we'll have "a.value" == "value(a)" == "value = a"Oooh it looks like this would be possible to write: 3.times = (int a) { Stdout(a.toUtf8).newline; } ...fun! :D
Aug 30 2007
Chris Nicholson-Sauls wrote:I reiterate what I've said about three times now: I watch as D slowly turns into Ruby. :)Hehe. They indeed have similarities - maybe not in language theory or overall concept, but in innovation. Having (part of) Ruby's expressiveness in D would be a very neat thing, as long as it doesn't affect other concepts and goals of D.(Although I actually like pseudo-members. ColdC has this as well, but by modifying a type-lib object; $String.foo() callable as "abc".foo() for example.)That's actually possible already in D (D1, even): // import tango.io.Stdout; void print (char[] s) { Stdout(s); } void main () { "Hello world!".print(); // omitting () is not possible, though } //
Aug 30 2007
Alexander Panek wrote:Chris Nicholson-Sauls wrote:I'm sure we'll never, ever, see something quite like: $db.commit transaction unless transaction.flag_set? :Simulate But other than that... ;)I reiterate what I've said about three times now: I watch as D slowly turns into Ruby. :)Hehe. They indeed have similarities - maybe not in language theory or overall concept, but in innovation. Having (part of) Ruby's expressiveness in D would be a very neat thing, as long as it doesn't affect other concepts and goals of D.Oh yes, I know. :) (See Cashew.) But unlike D/1.x, ColdC supports this for all types (in its own weird way). Right now it only works for arrays, and was originally just a fluke side-effect that got popular. It looks like D/2.x is going to open up that Pandora's Box though. Here's hoping it goes a lot better than the referenced myth. -- Chris Nicholson-Sauls(Although I actually like pseudo-members. ColdC has this as well, but by modifying a type-lib object; $String.foo() callable as "abc".foo() for example.)That's actually possible already in D (D1, even): // import tango.io.Stdout; void print (char[] s) { Stdout(s); } void main () { "Hello world!".print(); // omitting () is not possible, though } //
Aug 30 2007
kris wrote:Yeah, the proposed extensions raised all kinds of red flags for me at the conference. Bluntly, it felt like the notion of "structured programming" was being tossed out in favor of "slapdash programming" ... a brand new paradigm to go along with the other(s) being adopted :)What are the objections to this? Are there technical pitfalls? I liked to idea very much. It gives a flexible way of object-oriented / object-based programming similar to how I often see it implemented in C. Plus one can achieve a very nice syntactic sugar for call chaining, which is a great benefit I think. I thought this syntax for arrays is generally appreciated, so why not extend it for other types?
Aug 29 2007
Lutger wrote:kris wrote:Technical? Since when did that become important? ;) I belong to the "just because you can doesn't mean you should" camp, and feel that perhaps a more holistic view should be taken here? Just don't see this specific idiom as being particularly beneficial, without adding detrimental side-effect that I'll briefly touch on in a moment (it never really had significant value with arrays either, other than perhaps as a means to confuse non-experts O_+)Yeah, the proposed extensions raised all kinds of red flags for me at the conference. Bluntly, it felt like the notion of "structured programming" was being tossed out in favor of "slapdash programming" ... a brand new paradigm to go along with the other(s) being adopted :)What are the objections to this? Are there technical pitfalls?I liked to idea very much. It gives a flexible way of object-oriented / object-based programming similar to how I often see it implemented in C.And it potentially introduces additional namespace issues, hijacking issues, and compilation errors for large and/or long-term software development projects. The commercial-development space is where D ought to target, if it's to rise well above being just another enthusiasts playground :p A conservative approach would remove the existing idiom with arrays, rather than propagate it, and address concerns instead by perhaps example). Are you thinking this makes a good solution for 'properties' in general? As has been discussed recently?Plus one can achieve a very nice syntactic sugar for call chaining,D provides that already, no? Tango supports call-chaining extensively.which is a great benefit I think. I thought this syntax for arrays is generally appreciated, so why not extend it for other types?Just because some folks apparently like it, and are vocal about it, doesn't necessarily make it "generally appreciated"? That's a problem with newsgroups and forums though ... it's perhaps easy to get a skewed perspective? As for extending to other types, that's cool! I just feel this particular idiom potentially builds smoldering fires larger than the one(s) it is attempting to extinguish (or perhaps it's not even trying to resolve anything?). If that is the case it is hardly an adequate resolution, and will simply return to bite D in the buttocks. As such, I suspect alternatives should be given great consideration (or /greater/ consideration) and the relative trade-offs should be weighed appropriately. Yourself, and others, may feel that's not necessary or has been adequately performed already? I don't feel that way, and it's not the impression I got from the conference :-D (parts of this are written somewhat tongue-in-cheek, as there's only so much one can achieve via this medium. Please just take it as my opinion, and nothing more)
Aug 29 2007
"kris" <foo bar.com> wrote in message news:fb5742$nek$1 digitalmars.com...I think by call-chaining he was referring to cases such as join(reverse(split(toUpper(str)))) vs. str.toUpper.split.reverse.join(). The latter is arguably much more readable than the former.Plus one can achieve a very nice syntactic sugar for call chaining,D provides that already, no? Tango supports call-chaining extensively.
Aug 29 2007
Jarrett Billingsley wrote:"kris" <foo bar.com> wrote in message news:fb5742$nek$1 digitalmars.com...Had completely missed that, Jarret. Thanks, and fair pointI think by call-chaining he was referring to cases such as join(reverse(split(toUpper(str)))) vs. str.toUpper.split.reverse.join(). The latter is arguably much more readable than the former.Plus one can achieve a very nice syntactic sugar for call chaining,D provides that already, no? Tango supports call-chaining extensively.
Aug 29 2007
kris wrote:Lutger wrote:It will also be directly detrimental to maintainability when used for user defined types, as you no longer will be able to decide where a function is implemented by only looking at the call site (given inheritance and polymorphism this can in cases be difficult enough, but at least you have a type hierarchy to look to). -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tangokris wrote:And it potentially introduces additional namespace issues, hijacking issues, and compilation errors for large and/or long-term software development projects. The commercial-development space is where D ought to target, if it's to rise well above being just another enthusiasts playground :pYeah, the proposed extensions raised all kinds of red flags for me at the conference. Bluntly, it felt like the notion of "structured programming" was being tossed out in favor of "slapdash programming" ... a brand new paradigm to go along with the other(s) being adopted :)I liked to idea very much. It gives a flexible way of object-oriented / object-based programming similar to how I often see it implemented in C.
Aug 30 2007
Lars Ivar Igesund wrote:[...] It will also be directly detrimental to maintainability when used for user defined types, as you no longer will be able to decide where a function is implemented by only looking at the call site (given inheritance and polymorphism this can in cases be difficult enough, but at least you have a type hierarchy to look to).Well, usually a simple change to the import list will reveal where each functions are defined. I wouldn't see that as an argument against this feature. Apart from that, in an ideal world, the code is well documented enough to not have to determine the location of a function/method implementation yourself, anyways. Of course, this is the *ideal*, but maybe this encourages some to document better.
Aug 30 2007
Alexander Panek wrote:Lars Ivar Igesund wrote:I probably miss your point here, but it certainly shouldn't be necessary to change your code to find out what it does?[...] It will also be directly detrimental to maintainability when used for user defined types, as you no longer will be able to decide where a function is implemented by only looking at the call site (given inheritance and polymorphism this can in cases be difficult enough, but at least you have a type hierarchy to look to).Well, usually a simple change to the import list will reveal where each functions are defined. I wouldn't see that as an argument against this feature.Apart from that, in an ideal world, the code is well documented enough to not have to determine the location of a function/method implementation yourself, anyways. Of course, this is the *ideal*, but maybe this encourages some to document better.One should of course always document, but as many of the other suggestions in the Future of D presentation leans towards self documenting code (pure and nothrow functions for instance), I see this change as quite the opposite in that regard. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Aug 30 2007
Alexander Panek wrote:Lars Ivar Igesund wrote:On the other hand, the ambiguity problem: class A { int foo (int); } int foo (A, int); ..leads or at least may lead to maintenance problems, anyways. (Yes, I might have missed the point in the other post :P)[...] It will also be directly detrimental to maintainability when used for user defined types, as you no longer will be able to decide where a function is implemented by only looking at the call site (given inheritance and polymorphism this can in cases be difficult enough, but at least you have a type hierarchy to look to).Well, usually a simple change to the import list will reveal where each functions are defined. I wouldn't see that as an argument against this feature. Apart from that, in an ideal world, the code is well documented enough to not have to determine the location of a function/method implementation yourself, anyways. Of course, this is the *ideal*, but maybe this encourages some to document better.
Aug 30 2007
Alexander Panek wrote:Alexander Panek wrote:Perhaps, but even without interchangeability warning signs go up for me if you have a method and a function that have the same signature.Lars Ivar Igesund wrote:On the other hand, the ambiguity problem: class A { int foo (int); } int foo (A, int); ..leads or at least may lead to maintenance problems, anyways. (Yes, I might have missed the point in the other post :P)[...] It will also be directly detrimental to maintainability when used for user defined types, as you no longer will be able to decide where a function is implemented by only looking at the call site (given inheritance and polymorphism this can in cases be difficult enough, but at least you have a type hierarchy to look to).Well, usually a simple change to the import list will reveal where each functions are defined. I wouldn't see that as an argument against this feature. Apart from that, in an ideal world, the code is well documented enough to not have to determine the location of a function/method implementation yourself, anyways. Of course, this is the *ideal*, but maybe this encourages some to document better.
Aug 31 2007
kris wrote: ...And it potentially introduces additional namespace issues, hijacking issues, and compilation errors for large and/or long-term software development projects. The commercial-development space is where D ought to target, if it's to rise well above being just another enthusiasts playground :pI agree, although I am that enthusiast. The main reason I liked this feature is 1) see Jarret's post and 2) I find it is easier to write small classes and extend them with free functions, good class design is hard. But if there are such issues then it is probably not worth it.A conservative approach would remove the existing idiom with arrays, rather than propagate it, and address concerns instead by perhaps example). Are you thinking this makes a good solution for 'properties' in general? As has been discussed recently?No, not for properties. I never think of the current way properties are handled really as 'properties' in the sense of data members. They are just an alternative syntax for functions with 0 or 1 arguments in my book, with perhaps a hint to their role in a design. Now this is my opinion, maybe misinformed, but I don't think class properties are important. They are just dressed up getters/setters, which is not so good an idiom to use frequently.Just because some folks apparently like it, and are vocal about it, doesn't necessarily make it "generally appreciated"? That's a problem with newsgroups and forums though ... it's perhaps easy to get a skewed perspective?Sure, although I have never seen one single post that objects to array properties, nor have I encountered bugs / problems related to it.As for extending to other types, that's cool! I just feel this particular idiom potentially builds smoldering fires larger than the one(s) it is attempting to extinguish (or perhaps it's not even trying to resolve anything?). If that is the case it is hardly an adequate resolution, and will simply return to bite D in the buttocks.My impression was that it is mainly for syntactic sugar, and maybe there was a notion of how it could be used in generic programming? Can't think of an issue that it solves.As such, I suspect alternatives should be given great consideration (or /greater/ consideration) and the relative trade-offs should be weighed appropriately. Yourself, and others, may feel that's not necessary or has been adequately performed already? I don't feel that way, and it's not the impression I got from the conference :-DNo I don't pretend to have thought through the issues, I don't think I can. That's why I asked you!
Aug 30 2007
kris wrote:Lutger wrote:kris wrote:And it potentially introduces additional namespace issues, hijacking issues, and compilation errors for large and/or long-term software development projects. The commercial-development space is where D ought to target, if it's to rise well above being just another enthusiasts playground :pNamespace issues are why I don't currently find much use for the array trick. If you put your array trick functions in a module, they're mostly going to have short names like "find" and "index". So if you import that module normally it will clobber a valuable chunk of your namespace with little words like that. But doing a static or renamed import causes the things not to work. "arrayfn.find" can't be used as a property. Ok so you can static import and then alias just the ones you want to use in the current module, possibly down at function scope to limit the namespace clashing. But that's kind of a pain. The error messages are also not very intuitive currently. You type foo.bar(x,y) and get the error message "bar does not match types (int, int, int)" Wait -- I'm not even calling bar with three args!? Oh yeh that member syntax thing. And if there really *is* a member with that name in the current context then it will shadow the external one even though it *looks* like foo.bar should be unambiguously scoped by foo. These are from recent experience trying to emulate C++ iterators on top of D arrays. For instance I wanted to be able to say darray.begin() to get an iterator to an array. Forget it. Most classes in which I want to use that trick already have their own 'begin()' member which shadows the external begin(T)(T[]) function. So my feeling is that for this to be more useful: 1) Extension members should be marked as such and *only* be allowed to be called with member syntax. Those not marked as such will not be allowed to be called with member syntax. (if you need both then it's easy enough to write a trivial forwarding function.) 2) Inside a class/struct scope, lookup of foo.bar should ignore methods it already means extension members would do lookup differently than normal function lookup) --bb
Aug 30 2007
On Fri, 31 Aug 2007, Bill Baxter wrote:Namespace issues are why I don't currently find much use for the array trick. If you put your array trick functions in a module, they're mostly going to have short names like "find" and "index". So if you import that module normally it will clobber a valuable chunk of your namespace with little words like that. But doing a static or renamed import causes the things not to work. "arrayfn.find" can't be used as a property. Ok so you can static import and then alias just the ones you want to use in the current module, possibly down at function scope to limit the namespace clashing. But that's kind of a pain. The error messages are also not very intuitive currently. You type foo.bar(x,y) and get the error message "bar does not match types (int, int, int)" Wait -- I'm not even calling bar with three args!? Oh yeh that member syntax thing. And if there really *is* a member with that name in the current context then it will shadow the external one even though it *looks* like foo.bar should be unambiguously scoped by foo. These are from recent experience trying to emulate C++ iterators on top of D arrays. For instance I wanted to be able to say darray.begin() to get an iterator to an array. Forget it. Most classes in which I want to use that trick already have their own 'begin()' member which shadows the external begin(T)(T[]) function. So my feeling is that for this to be more useful: 1) Extension members should be marked as such and *only* be allowed to be called with member syntax. Those not marked as such will not be allowed to be called with member syntax. (if you need both then it's easy enough to write a trivial forwarding function.) 2) Inside a class/struct scope, lookup of foo.bar should ignore methods of the means extension members would do lookup differently than normal function lookup) --bbDon't overlook the changes upcoming in 2.0 to the overload resolution logic. They'll greatly reduce (if not eliminate) the problem. Many of the changes in 2.0 in isolation might introduce problems, but together make for a more powerful whole. Later, Brad
Aug 30 2007
Brad Roberts wrote:On Fri, 31 Aug 2007, Bill Baxter wrote:Yeh, that should help some. But that doesn't seem to do anything about foo.bar() inside a class being treated as this.bar(foo). I think that just shouldn't happen ever. Maybe that's just a bug, though. In fact I think I'll go file it as one right now. --bbNamespace issues are why I don't currently find much use for the array trick. If you put your array trick functions in a module, they're mostly going to have short names like "find" and "index". So if you import that module normally it will clobber a valuable chunk of your namespace with little words like that. But doing a static or renamed import causes the things not to work. "arrayfn.find" can't be used as a property. Ok so you can static import and then alias just the ones you want to use in the current module, possibly down at function scope to limit the namespace clashing. But that's kind of a pain. The error messages are also not very intuitive currently. You type foo.bar(x,y) and get the error message "bar does not match types (int, int, int)" Wait -- I'm not even calling bar with three args!? Oh yeh that member syntax thing. And if there really *is* a member with that name in the current context then it will shadow the external one even though it *looks* like foo.bar should be unambiguously scoped by foo. These are from recent experience trying to emulate C++ iterators on top of D arrays. For instance I wanted to be able to say darray.begin() to get an iterator to an array. Forget it. Most classes in which I want to use that trick already have their own 'begin()' member which shadows the external begin(T)(T[]) function. So my feeling is that for this to be more useful: 1) Extension members should be marked as such and *only* be allowed to be called with member syntax. Those not marked as such will not be allowed to be called with member syntax. (if you need both then it's easy enough to write a trivial forwarding function.) 2) Inside a class/struct scope, lookup of foo.bar should ignore methods of the means extension members would do lookup differently than normal function lookup) --bbDon't overlook the changes upcoming in 2.0 to the overload resolution logic. They'll greatly reduce (if not eliminate) the problem. Many of the changes in 2.0 in isolation might introduce problems, but together make for a more powerful whole.
Aug 30 2007
Bill Baxter wrote:kris wrote:AmenLutger wrote:kris wrote:And it potentially introduces additional namespace issues, hijacking issues, and compilation errors for large and/or long-term software development projects. The commercial-development space is where D ought to target, if it's to rise well above being just another enthusiasts playground :pNamespace issues are why I don't currently find much use for the array trick. If you put your array trick functions in a module, they're mostly going to have short names like "find" and "index". So if you import that module normally it will clobber a valuable chunk of your namespace with little words like that. But doing a static or renamed import causes the things not to work. "arrayfn.find" can't be used as a property. Ok so you can static import and then alias just the ones you want to use in the current module, possibly down at function scope to limit the namespace clashing. But that's kind of a pain. The error messages are also not very intuitive currently. You type foo.bar(x,y) and get the error message "bar does not match types (int, int, int)" Wait -- I'm not even calling bar with three args!? Oh yeh that member syntax thing. And if there really *is* a member with that name in the current context then it will shadow the external one even though it *looks* like foo.bar should be unambiguously scoped by foo. These are from recent experience trying to emulate C++ iterators on top of D arrays. For instance I wanted to be able to say darray.begin() to get an iterator to an array. Forget it. Most classes in which I want to use that trick already have their own 'begin()' member which shadows the external begin(T)(T[]) function. So my feeling is that for this to be more useful: 1) Extension members should be marked as such and *only* be allowed to be called with member syntax. Those not marked as such will not be allowed to be called with member syntax. (if you need both then it's easy enough to write a trivial forwarding function.) 2) Inside a class/struct scope, lookup of foo.bar should ignore methods it already means extension members would do lookup differently than normal function lookup) --bb
Aug 30 2007
Bill Baxter wrote:kris wrote:Or just use selective import to do the same thing: import cashew .utils .Array : contains, push, pop ;Lutger wrote:kris wrote:And it potentially introduces additional namespace issues, hijacking issues, and compilation errors for large and/or long-term software development projects. The commercial-development space is where D ought to target, if it's to rise well above being just another enthusiasts playground :pNamespace issues are why I don't currently find much use for the array trick. If you put your array trick functions in a module, they're mostly going to have short names like "find" and "index". So if you import that module normally it will clobber a valuable chunk of your namespace with little words like that. But doing a static or renamed import causes the things not to work. "arrayfn.find" can't be used as a property. Ok so you can static import and then alias just the ones you want to use in the current module, possibly down at function scope to limit the namespace clashing. But that's kind of a pain.The error messages are also not very intuitive currently. You type foo.bar(x,y) and get the error message "bar does not match types (int, int, int)" Wait -- I'm not even calling bar with three args!? Oh yeh that member syntax thing. And if there really *is* a member with that name in the current context then it will shadow the external one even though it *looks* like foo.bar should be unambiguously scoped by foo.I agree; but I consider it a lookup bug, not an inherent aspect of pseudo-members.These are from recent experience trying to emulate C++ iterators on top of D arrays. For instance I wanted to be able to say darray.begin() to get an iterator to an array. Forget it. Most classes in which I want to use that trick already have their own 'begin()' member which shadows the external begin(T)(T[]) function.static import FooBar foo.bar : begin ; alias FooBar.begin fb_begin ; //... darray.fb_begin() Yeah, okay, that is a bit borked.So my feeling is that for this to be more useful: 1) Extension members should be marked as such and *only* be allowed to be called with member syntax. Those not marked as such will not be allowed to be called with member syntax. (if you need both then it's easy enough to write a trivial forwarding function.)Its not a bad idea. The "trivial forwarding function" should be inlineable anyhow. Maybe a "context" parameter? Something like: size_t indexOf : T[] array (T) (T elem) { ... } Where the (':' param) after the function name creates the context-param. Other examples: ulong area : IShape shp () { ... } void unique : inout T[] array (T) () { ... } Its just a random on-the-spot idea.2) Inside a class/struct scope, lookup of foo.bar should ignore methods it already means extension members would do lookup differently than normal function lookup)Aye. -- Chris Nicholson-Sauls
Aug 30 2007
Chris Nicholson-Sauls wrote:Bill Baxter wrote:kris wrote:Lutger wrote:kris wrote:Maybe even just use a semi-colon instead of comma in the arg list? size_t indexOf(T)(T[] array; T elem) { ... } ulong area (IShape shp;) { ... } void unique (ref T[] array; T) () { ... } --bbSo my feeling is that for this to be more useful: 1) Extension members should be marked as such and *only* be allowed to be called with member syntax. Those not marked as such will not be allowed to be called with member syntax. (if you need both then it's easy enough to write a trivial forwarding function.)Its not a bad idea. The "trivial forwarding function" should be inlineable anyhow. Maybe a "context" parameter? Something like: size_t indexOf : T[] array (T) (T elem) { ... } Where the (':' param) after the function name creates the context-param. Other examples: ulong area : IShape shp () { ... } void unique : inout T[] array (T) () { ... } Its just a random on-the-spot idea.
Aug 30 2007
Bill Baxter wrote:Chris Nicholson-Sauls wrote:I like that syntax; something similiar is used in mathematics on occasion. Simple and elegant. Thanks, Nathan ReedBill Baxter wrote:Maybe even just use a semi-colon instead of comma in the arg list? size_t indexOf(T)(T[] array; T elem) { ... } ulong area (IShape shp;) { ... } void unique (ref T[] array; T) () { ... } --bbkris wrote: So my feeling is that for this to be more useful: 1) Extension members should be marked as such and *only* be allowed to be called with member syntax. Those not marked as such will not be allowed to be called with member syntax. (if you need both then it's easy enough to write a trivial forwarding function.)Its not a bad idea. The "trivial forwarding function" should be inlineable anyhow. Maybe a "context" parameter? Something like: size_t indexOf : T[] array (T) (T elem) { ... } Where the (':' param) after the function name creates the context-param. Other examples: ulong area : IShape shp () { ... } void unique : inout T[] array (T) () { ... } Its just a random on-the-spot idea.
Aug 30 2007
Nathan Reed wrote:Bill Baxter wrote:Agreed. I believe the use of semicolons within params was once suggested for another purpose, ages ago, and (obviously) went nowhere. Maybe this suggestion will be a bit more lucky. -- Chris Nicholson-SaulsChris Nicholson-Sauls wrote:I like that syntax; something similiar is used in mathematics on occasion. Simple and elegant. Thanks, Nathan ReedBill Baxter wrote:Maybe even just use a semi-colon instead of comma in the arg list? size_t indexOf(T)(T[] array; T elem) { ... } ulong area (IShape shp;) { ... } void unique (ref T[] array; T) () { ... } --bbkris wrote: So my feeling is that for this to be more useful: 1) Extension members should be marked as such and *only* be allowed to be called with member syntax. Those not marked as such will not be allowed to be called with member syntax. (if you need both then it's easy enough to write a trivial forwarding function.)Its not a bad idea. The "trivial forwarding function" should be inlineable anyhow. Maybe a "context" parameter? Something like: size_t indexOf : T[] array (T) (T elem) { ... } Where the (':' param) after the function name creates the context-param. Other examples: ulong area : IShape shp () { ... } void unique : inout T[] array (T) () { ... } Its just a random on-the-spot idea.
Aug 30 2007
Michael Deardeuff wrote:I am very excited about the future of D. Walter's and Andrei's talk at the conference was awesome. However, there are still a few quirks to get out: This is regarding slide 9 of the presentation. I noticed that most people at the conference liked the idea of extending library classes, but were not to pleased with the interchangability of --- foo(a, args) --- and --- a.foo(args) --- like the arrays have. ---- class A {...} ... extension class A { void foo(args) {...} } ... a.foo(args); ---- (maybe the syntax could be "class extension A" or "extension A"...) In this way class extensions are clearly marked and the syntax is consistent. It would be easy to add interfaces to the library class: extension A : Visitable { void accept(Visitor v) {...} } Just an idea for you guys, Walter, Andrei, and the community. --Michael DeardeuffI'm on the camp that like the interchangeable method/function syntax because it will encourage people to write better code, rather then sticking everything into the class body. It also allows you to change methods into functions and visa versa without breaking the users code. -Joel
Aug 31 2007
janderson wrote:Michael Deardeuff wrote:Here's a thought. Will this work with C code such that we could for instance expose a class C++ in C like form and then use it in D like a regular class, and visa versa? Note of course would only applies to classes without V-Tables.I am very excited about the future of D. Walter's and Andrei's talk at the conference was awesome. However, there are still a few quirks to get out: This is regarding slide 9 of the presentation. I noticed that most people at the conference liked the idea of extending library classes, but were not to pleased with the interchangability of --- foo(a, args) --- and --- a.foo(args) --- like the arrays have. ---- class A {...} ... extension class A { void foo(args) {...} } ... a.foo(args); ---- (maybe the syntax could be "class extension A" or "extension A"...) In this way class extensions are clearly marked and the syntax is consistent. It would be easy to add interfaces to the library class: extension A : Visitable { void accept(Visitor v) {...} } Just an idea for you guys, Walter, Andrei, and the community. --Michael DeardeuffI'm on the camp that like the interchangeable method/function syntax because it will encourage people to write better code, rather then sticking everything into the class body. It also allows you to change methods into functions and visa versa without breaking the users code. -Joel
Aug 31 2007