Re: The magic behind foreach (was: Re: Descent 0.5.3 released)
On Fri, Jan 23, 2009 at 12:30 AM, Bill Baxter wrote: > > I see what you're saying now. So the user has to manipulate a bool > return value instead of an int? > > Then you could have > > void opApply(bool delegate(ref int) dg) { > foreach(i; internal_) { >if (dg(i)) return; > } > } > > Yep, that looks like an improvement to me. Right. Granted, it's not perfect - it's still possible to write an opApply that doesn't respect breaks/returns/gotos out of the loop - but it's much more straightforward. A "perfect" opApply would probably look like: void opApply(void delegate(ref int) dg) { foreach(i; mData) dg(i); } but it would probably have to abuse exceptions to accomplish this, which doesn't sound like a great idea to me.
Re: The magic behind foreach (was: Re: Descent 0.5.3 released)
On Fri, Jan 23, 2009 at 11:59 AM, Jarrett Billingsley wrote: > On Thu, Jan 22, 2009 at 9:38 PM, Bill Baxter wrote: >> >> Yep, that was the gist of it. Put the return value on the stack of >> the calling frame. >> Nothing all that fancy really, just you want to be able to hide that >> __result = blah ugliness from the user. > > Oh, I'm suggesting that the compiler do this instead of us having to > do it with macros. I see what you're saying now. So the user has to manipulate a bool return value instead of an int? Then you could have void opApply(bool delegate(ref int) dg) { foreach(i; internal_) { if (dg(i)) return; } } Yep, that looks like an improvement to me.
Re: The magic behind foreach (was: Re: Descent 0.5.3 released)
On Thu, Jan 22, 2009 at 9:38 PM, Bill Baxter wrote: > > Yep, that was the gist of it. Put the return value on the stack of > the calling frame. > Nothing all that fancy really, just you want to be able to hide that > __result = blah ugliness from the user. Oh, I'm suggesting that the compiler do this instead of us having to do it with macros.
Re: Any chance to call Tango as Extended Standard Library
On 2009-01-19 18:11:15 -0500, Sergey Gromov said: I think "can't" is a bit strong a statement. Let's see: With opApply: class progressUpdater(Collection) { this(Collection c) { collection_ = c; } int opApply(int delegate(ref ElementType!(Collection)) dg) { composed_ = dg; return collection_.opApply(&fancifier); } private: int fancifier(ref ElementType!(Collection) el) { globalOnProgress(); return composed_(el); } Collection collection_; int delegate(ref ElementType!(Collection)) composed_; } I think it's the same as this: class progressUpdater(Collection) { this(Collection c) { collection_ = c; } int opApply(int delegate(ref ElementType!(Collection)) dg) { int fancifier(ref ElementType!(Collection) el) { globalOnProgress(); return composed_(el); } composed_ = dg; return collection_.opApply(&fancifier); } private: Collection collection_; } Or this: class progressUpdater(Collection) { this(Collection c) { collection_ = c; } int opApply(int delegate(ref ElementType!(Collection)) dg) { foreach(ref ElementType!(Collection) el; collection_) { globalOnProgress(); if (dg(el)) return 1; } return 0; } private: Collection collection_; } -- Michel Fortin michel.for...@michelf.com http://michelf.com/
Re: The magic behind foreach (was: Re: Descent 0.5.3 released)
On Fri, Jan 23, 2009 at 11:15 AM, Jarrett Billingsley wrote: > On Thu, Jan 22, 2009 at 7:00 PM, Bill Baxter wrote: >> >> I posted a proposal for how to hide the magic int from the user a >> while back, but my conclusion was that my approach would require AST >> macros in order to give it a reasonable syntax. With the ast macros >> you'd be able to do something like yield(i) in the body of your >> foreach, where yield is an appropriately defined macro. >> > > Consider the case where you return a value inside a foreach loop: > > int find(char[] value) > { >foreach(k, v; someAA) >if(v == value) >return k; > } > > How is this implemented? It puts a local variable in the stack frame > of find(), called __result. Then the foreach delegate just writes > into that local when it returns (__result = k; return > IM_RETURNING_NOW;), and the compiler-generated cruft returns the value > of that local from find() (switch(...) { case IM_RETURNING_NOW: return > __result; }). > > The delegate return status code doesn't have to be any different. > Just have the delegate return a bool (should iteration stop?) and put > its actual return status in the stack frame of the enclosing function. Yep, that was the gist of it. Put the return value on the stack of the calling frame. Nothing all that fancy really, just you want to be able to hide that __result = blah ugliness from the user. --bb
Re: Any chance to call Tango as Extended Standard Library
On Thu, Jan 22, 2009 at 8:13 PM, Stewart Gordon wrote: > Don wrote: > >> >> The other option (which I would prefer) is for druntime to get bigger, and >> encompass more of the common code from both. So that both Phobos and Tango >> became (crucial) extension libraries over a small core. And the bigger that >> common core becomes, the smaller the library problem becomes. > > Up until the point at which somebody decides it's time to develop a library > to rival druntime. And we prevent that from happening by making as many people as possible happy with the development and features of druntime/core. This is exactly what caused the split in libraries in the first place - a sizable contingent of users who _weren't_ happy with the existing library or its development. In the end though, of course there's nothing we can do from stopping people from developing yet another library. But we can at least try to reduce the likelihood of it.
Re: The magic behind foreach (was: Re: Descent 0.5.3 released)
On Thu, Jan 22, 2009 at 7:00 PM, Bill Baxter wrote: > > I posted a proposal for how to hide the magic int from the user a > while back, but my conclusion was that my approach would require AST > macros in order to give it a reasonable syntax. With the ast macros > you'd be able to do something like yield(i) in the body of your > foreach, where yield is an appropriately defined macro. > Consider the case where you return a value inside a foreach loop: int find(char[] value) { foreach(k, v; someAA) if(v == value) return k; } How is this implemented? It puts a local variable in the stack frame of find(), called __result. Then the foreach delegate just writes into that local when it returns (__result = k; return IM_RETURNING_NOW;), and the compiler-generated cruft returns the value of that local from find() (switch(...) { case IM_RETURNING_NOW: return __result; }). The delegate return status code doesn't have to be any different. Just have the delegate return a bool (should iteration stop?) and put its actual return status in the stack frame of the enclosing function.
Re: Any chance to call Tango as Extended Standard Library
Don wrote: The other option (which I would prefer) is for druntime to get bigger, and encompass more of the common code from both. So that both Phobos and Tango became (crucial) extension libraries over a small core. And the bigger that common core becomes, the smaller the library problem becomes. Up until the point at which somebody decides it's time to develop a library to rival druntime. Stewart.
Re: Pluggable type sytems
"bearophile" wrote in message news:gl0ohe$1gd...@digitalmars.com... >I think pluggable type systems will become more common in the following >years (see also the optional annotations of Python3 that are designed for >that too). This is more or less related: > > http://bartoszmilewski.wordpress.com/2009/01/18/java-pluggable-types/ > > (but nonnullability is so basic that it's better inside the language, and > not left out to a plug-in type system). > > Bye, > bearophile Interesting article. Sounds a lot like D2 but with that flow-analysis nice-ity, and @PolyNull (which has been proposed here...often). Although I wonder...maybe @PolyNull should be the default (wherever applicable) instead of @Nullable or @NonNull? (Or maybe I'm overlooking some obvious problem with that.) I see pluggable type sytems as potentially being a specific form of a more general thing I've been observing an increasing need for/trend towards: customizable languages. Ex: A language that doesn't say "Semicolons mark end-of-statement" or "Newline marks end-of-statement and lines can be split with a backslash", but provides both as mutually-exclusive programmer-selectable options. Or a choice of C-style curly-braces vs Python-style indentation. Etc. (Side note: This stuff could really cut down on religious language debates. Not eliminate, of course, but reduce.) Also, a tool could then be used to translate code between the various options, maybe even integrated into the IDE, so that people working on multi-person projects could each set up their own environments and use their own "customized language" even while working on the same line of code. The only project-wide standard would be what settings are used for checked-in code, just like tab/space settings and EOL markers (but ideally performed automatically (and reliably) by the check-in/check-out process). Eventually this might even be generalizable to the point where most languages can be reduced to nothing more than a collection of language settings. Which I think is the direction we appear to be headed anyway, since it seems like everyone and their grandmother is designing their own language (or two) these days, and many of these languages are more-or-less "just like language X, but with A, B and C changed to be more like language Y." Obviously this is all much easier said than done, but it's something I've been thinking a lot about lately, and I think may be worth exploring.
Re: The magic behind foreach (was: Re: Descent 0.5.3 released)
On Fri, Jan 23, 2009 at 8:52 AM, Ary Borenszweig wrote: > Bill Baxter wrote: >> >> On Fri, Jan 23, 2009 at 8:10 AM, Christopher Wright >> wrote: >>> >>> Ary Borenszweig wrote: If the compiler can transform a "foreach" into an opApply call, passing the foreach body and converting breaks to "return 1" statements... can't opApply be specified as: int opApply(void delegate(ref uint) dg) { // note: delegate returns void } and the compiler transforms the opApply signature to the one that's used now, plus converting each dg call to a call and a check of return value != 0 and return 1 in that case? >>> >>> This only fails if you wish to take a particular action when the calling >>> code breaks out of iteration. This is not such a large use case that I >>> think >>> it worth preserving. > > Why do you mean by "fails"? The compiler transforms the foreach's body, it > can transform the opApply's body. > >> >> It's not? >> >> foreach(i; things) { >> if (i==a) continue; >> if (i==b) break; >> if (i==d) return; >> if (i==c) goto somewhere; >> } >> >> Those are all fairly common things to do from inside the 'dg' call. >> The int is how the compiler distinguishes which case got you out of >> the dg. >> >> --bb > > Aaaah... Now I see what's the return value of opApply for. So I tried your > code: > > (just the relevant piece) > --- > int main(char[][] args) { >int a = 1, b = 2, c = 3, d = 4; > >Foo foo = new Foo(); >foreach(i; foo) { >if (i==a) continue; >if (i==b) break; >if (i==d) return; >if (i==c) goto somewhere; >} > >somewhere: > >return 0; > } > --- > > and DMD spits out this: > > --- > int main(char[][] args) { >int a = 1, b = 2, c = 3, d = 4; > >Foo foo = new Foo; >switch(foo.opApply(delegate (uint __applyArg0) { >{ >uint i = __applyArg0; >if(i == cast(uint) a) >return 0; >if(i == cast(uint) b) >return 1; >if(i == cast(uint) d) >return 2; >if(i == cast(uint) c) >return 3; >} >return 0; >} )) { >default: >break; >case 2: >return; >case 3: >goto somewhere; >} > >somewhere: > >return 0; > } > --- > > Intersting. The compiler (Walter?) is being smart here. :-) I posted a proposal for how to hide the magic int from the user a while back, but my conclusion was that my approach would require AST macros in order to give it a reasonable syntax. With the ast macros you'd be able to do something like yield(i) in the body of your foreach, where yield is an appropriately defined macro. If anyone is interested I'll try to dig it up from the archives. --bb
Re: The magic behind foreach (was: Re: Descent 0.5.3 released)
Bill Baxter wrote: On Fri, Jan 23, 2009 at 8:10 AM, Christopher Wright wrote: Ary Borenszweig wrote: If the compiler can transform a "foreach" into an opApply call, passing the foreach body and converting breaks to "return 1" statements... can't opApply be specified as: int opApply(void delegate(ref uint) dg) { // note: delegate returns void } and the compiler transforms the opApply signature to the one that's used now, plus converting each dg call to a call and a check of return value != 0 and return 1 in that case? This only fails if you wish to take a particular action when the calling code breaks out of iteration. This is not such a large use case that I think it worth preserving. Why do you mean by "fails"? The compiler transforms the foreach's body, it can transform the opApply's body. It's not? foreach(i; things) { if (i==a) continue; if (i==b) break; if (i==d) return; if (i==c) goto somewhere; } Those are all fairly common things to do from inside the 'dg' call. The int is how the compiler distinguishes which case got you out of the dg. --bb Aaaah... Now I see what's the return value of opApply for. So I tried your code: (just the relevant piece) --- int main(char[][] args) { int a = 1, b = 2, c = 3, d = 4; Foo foo = new Foo(); foreach(i; foo) { if (i==a) continue; if (i==b) break; if (i==d) return; if (i==c) goto somewhere; } somewhere: return 0; } --- and DMD spits out this: --- int main(char[][] args) { int a = 1, b = 2, c = 3, d = 4; Foo foo = new Foo; switch(foo.opApply(delegate (uint __applyArg0) { { uint i = __applyArg0; if(i == cast(uint) a) return 0; if(i == cast(uint) b) return 1; if(i == cast(uint) d) return 2; if(i == cast(uint) c) return 3; } return 0; } )) { default: break; case 2: return; case 3: goto somewhere; } somewhere: return 0; } --- Intersting. The compiler (Walter?) is being smart here. :-)
Re: The magic behind foreach (was: Re: Descent 0.5.3 released)
On Fri, Jan 23, 2009 at 8:10 AM, Christopher Wright wrote: > Ary Borenszweig wrote: >> >> If the compiler can transform a "foreach" into an opApply call, passing >> the foreach body and converting breaks to "return 1" statements... can't >> opApply be specified as: >> >> int opApply(void delegate(ref uint) dg) { // note: delegate returns void >> } >> >> and the compiler transforms the opApply signature to the one that's used >> now, plus converting each dg call to a call and a check of return value != >> 0 and return 1 in that case? > > This only fails if you wish to take a particular action when the calling > code breaks out of iteration. This is not such a large use case that I think > it worth preserving. It's not? foreach(i; things) { if (i==a) continue; if (i==b) break; if (i==d) return; if (i==c) goto somewhere; } Those are all fairly common things to do from inside the 'dg' call. The int is how the compiler distinguishes which case got you out of the dg. --bb
Re: The magic behind foreach (was: Re: Descent 0.5.3 released)
Ary Borenszweig wrote: If the compiler can transform a "foreach" into an opApply call, passing the foreach body and converting breaks to "return 1" statements... can't opApply be specified as: int opApply(void delegate(ref uint) dg) { // note: delegate returns void } and the compiler transforms the opApply signature to the one that's used now, plus converting each dg call to a call and a check of return value != 0 and return 1 in that case? This only fails if you wish to take a particular action when the calling code breaks out of iteration. This is not such a large use case that I think it worth preserving.
Re: Any chance to call Tango as Extended Standard Library
Denis Koroskin Wrote: > I think believe we could take advantage of current state of both libraries in > D2 - they are both incomplete and being redesigned to fit D2 better. > We could revisit both Tango and Phobos, and clean them up by removing > outdated modules and modules with same functionality. This will make Phobos > really small and much easier to learn. > > On the other hand, Tango will continue providing all the extended > functionality. > > Here is a list of Phobos modules that I believe could be safely removed: > > - crc32 and std.md5 - these should be deprecated in favor of > tango.io.digest.Crc32 and tango.io.digest.Md5 > Tango is better designed and has support for other algoriths (MD2, MD4, > SHA256, SHA512, Tiger and more). > See http://www.dsource.org/projects/tango/wiki/ChapterEncodingAndCrypto for > details. > > - std.atomics - tango.core.Atomic is superior to it (std.atomics has nothing > but CAS anyway). > - std.base64 - deprecate in favor of tango.io.encode.Base64 > - std.cover - is it supposed to be visible to user? Should it be in Phobos? > - std.loader - deprecate in favor of tango.sys.SharedLib > - std.bitarray > - std.openrj > - std.process - merge with tango.sys.Process > - std.regexp - buggy, deprecate in favor of tango.text.Regex > - std.socket, std.socketstream - deprecate in favor of tango.net.* > - std.uni - deprecate in favor of tango.text.Unicode > - std.uri - deprecate in favor of tango.net.Uri > - std.xml - deprecate in favor of tango.text.xml.* > - std.zip and std.zlib - deprecate in favor of tango.io.compress.* > > In almost *all* cases Tango has cleaner, faster and less buggy implementation > of the same functionality. That's an interesting list. Without the ability to distribute Phobos and Tango together from the digitalmars.com site, I doubt anything will get dropped from Phobos in favor of what is in Tango. For a combined distribution to ever occur requires a whole lot more coordination between Phobos and Tango that I doubt we'll see for a very long time. > Other modules - does anyone use any of these: > std.bitmanip > std.bind > std.boxer > std.outbuffer > std.stdint > std.syserror > std.system > ? std.bind is useful for binding data that will change before the delegate is called. I've used bind a lot when doing inter-thread communication with queues of pending commands. I'd also like to use a variant of bit array with fixed sizes, easier initialiation, and uses the SSE instruction set. Right now, neither Phobos nor Tango contains what I want.
Re: Any chance to call Tango as Extended Standard Library
On Thu, 22 Jan 2009 18:11:02 +0100, Jarrett Billingsley wrote: On Thu, Jan 22, 2009 at 1:53 AM, Alexander Pánek wrote: John Reimer wrote: Don wrote: The other option (which I would prefer) is for druntime to get bigger, and encompass more of the common code from both. So that both Phobos and Tango became (crucial) extension libraries over a small core. And the bigger that common core becomes, the smaller the library problem becomes. Actually, I very much like that idea. And it seems to make sense too. Seconded! That's a nice idea. Thirded. Fourthed! -- Simen
Re: Protection in BaseClassList: semantics undefined?
Jarrett Billingsley schrieb: > As far as most people can tell, it's an artifact from very early on in > D's development. It was probably originally supposed to have MI but > that was dropped. The compiler accepts public/private/protected on > the base class but it's useless as it breaks things. http://d.puremagic.com/issues/show_bug.cgi?id=177
Re: Any chance to call Tango as Extended Standard Library
Sergey Gromov wrote: Mon, 19 Jan 2009 06:15:06 -0800, Andrei Alexandrescu wrote: Michel Fortin wrote: Other possible things involves a rudimentary profiler (checking for the elapsed time at each loop iteration), or a progress monitoring template (notifying another thread of the progress of a particular task). foreach (task; progessUpdater(timeProfiler(listOfTasks))) { ... } You can't compose iteration based on opApply. How would progessUpdater and timeProfiler look like? This example pretty much transforms your argument into mine :o). I think "can't" is a bit strong a statement. Let's see: With opApply: class progressUpdater(Collection) { this(Collection c) { collection_ = c; } int opApply(int delegate(ref ElementType!(Collection)) dg) { composed_ = dg; return collection_.opApply(&fancifier); } private: int fancifier(ref ElementType!(Collection) el) { globalOnProgress(); return composed_(el); } Collection collection_; int delegate(ref ElementType!(Collection)) composed_; } I see. Very ingenious! Reversed flow of control all the way. Thanks. Andrei
Re: Any chance to call Tango as Extended Standard Library
On Thu, Jan 22, 2009 at 1:53 AM, Alexander Pánek wrote: > John Reimer wrote: >> >> Don wrote: >>> >>> The other option (which I would prefer) is for druntime to get bigger, >>> and encompass more of the common code from both. So that both Phobos >>> and Tango became (crucial) extension libraries over a small core. And >>> the bigger that common core becomes, the smaller the library problem >>> becomes. >> >> Actually, I very much like that idea. And it seems to make sense too. > > Seconded! That's a nice idea. > Thirded.
Re: Any chance to call Tango as Extended Standard Library
Don wrote: Daniel Keep wrote: Andrei Alexandrescu wrote: Don wrote: [snip] It means that any code which uses a library based on both Tango and a library based on Phobos will end up with two copies of all of the functions, and they'll have different name mangling etc. You end up with two incompatible Bigints, for example, even though they have identical code inside. Oh, I see. You want your library to be usable whether the end user prefers Phobos or Tango. But then why not stick it into a namespace of your choosing? Let's say your libraries are general enough to warrant putting them in a common core, but then anyone who defines some library don't have to go to the "core ombudsman" to add it to the common namespace. They'd just create unique namespaces of their own. No? Andrei I think he means this: let's say you're writing app A. A depends on libraries B and C. B depends on Phobos, and C depends on Tango. Both B and C happen to use BigInts or IO or anything else that isn't shared. All of a sudden, you've now got to link in TWO standard libraries instead of just one, each with potentially duplicated code. And you can't obtain a BigInt from library B and pass it into library C, since they are different types; even though they have 100% identical source code except for the name. This will partially be solved by structural casts. I have an implementation but haven't put it in phobos yet. Structural casts will allow types that have the same layout to be cast to one another. Of course, that's still not ideal but it's one step forward. Andrei
Re: Any chance to call Tango as Extended Standard Library
Daniel Keep wrote: Andrei Alexandrescu wrote: Don wrote: [snip] It means that any code which uses a library based on both Tango and a library based on Phobos will end up with two copies of all of the functions, and they'll have different name mangling etc. You end up with two incompatible Bigints, for example, even though they have identical code inside. Oh, I see. You want your library to be usable whether the end user prefers Phobos or Tango. But then why not stick it into a namespace of your choosing? Let's say your libraries are general enough to warrant putting them in a common core, but then anyone who defines some library don't have to go to the "core ombudsman" to add it to the common namespace. They'd just create unique namespaces of their own. No? Andrei I think he means this: let's say you're writing app A. A depends on libraries B and C. B depends on Phobos, and C depends on Tango. Both B and C happen to use BigInts or IO or anything else that isn't shared. All of a sudden, you've now got to link in TWO standard libraries instead of just one, each with potentially duplicated code. And you can't obtain a BigInt from library B and pass it into library C, since they are different types; even though they have 100% identical source code except for the name. From personal experience, the alternative isn't much better: writing code that switches between the two. I have an XML library that can use either Phobos or Tango. It does this by implementing all the calls it needs in a shim library, essentially using it's own standard library. It gets really fun when you need to implement some call that's trivial in one library, but really hard in the other. I remember having to build an IO layer so that both Phobos and Tango had the same semantics regarding EOF or something... Urgh. -- Daniel
Re: Any chance to call Tango as Extended Standard Library
Andrei Alexandrescu wrote: Don wrote: Andrei Alexandrescu wrote: Don wrote: Andrei Alexandrescu wrote: IUnknown wrote: Regarding Phobos + Tango, the minimum I expect is things like containers, algorithm and common math stuff to be in one core module. This is already bound to be an issue because there is disagreement on how e.g. containers should look like (Java-style vs. STL-style). Which should be chosen? This naturally influences how algorithms are defined. Andrei The analogy with KDE vs Gnome doesn't seem valid to me -- most libraries will work regardless of which GUI library is chosen. Programmers can still rely on the Posix and C standard libraries. I agree. Can we work out the math stuff at least? There's no difference between Phobos and Tango there. All we need is an agreement on common module naming (eg, create core.math). That would be great. I don't think that's a major issue anyway. If I were you, to be compatible with today's state of affairs, I'd simply put in the makefile the code necessary for switching the module prefixes. It means that any code which uses a library based on both Tango and a library based on Phobos will end up with two copies of all of the functions, and they'll have different name mangling etc. You end up with two incompatible Bigints, for example, even though they have identical code inside. Oh, I see. You want your library to be usable whether the end user prefers Phobos or Tango. But then why not stick it into a namespace of your choosing? Let's say your libraries are general enough to warrant putting them in a common core, but then anyone who defines some library don't have to go to the "core ombudsman" to add it to the common namespace. They'd just create unique namespaces of their own. No? That's possible too. Originally, my code was in the 'mathextra' namespace, and I'm somewhat regretting moving it it out. You still need an ombudsman, though, to determine which libraries are standard, and which are not, in order to prevent namespace collisions. Personally, I like the boost model -- all you need is a root level (like 'boost') to act as a namespace protection mechanism, and then a library standardisation policy. But then you have the question as to the organisation of the 'std' namespace -- for example, it contains such obscure stuff as std.openrj which is actually a stand-alone library. (I notice Dennis has just posted some similar sentiments, so I'll stop for now). It could be that all that we need is to create a standard naming policy.
Re: Protection in BaseClassList: semantics undefined?
On Thu, Jan 22, 2009 at 9:43 AM, Harry Vennik wrote: > Hi, > > > http://www.digitalmars.com/d/2.0/class.html > > In the grammar specification I read that a base class or interface name can > be prepended a protection attribute. But I don't find a word about the > semantics thereof... Can anyone tell (and update the docs)? As far as most people can tell, it's an artifact from very early on in D's development. It was probably originally supposed to have MI but that was dropped. The compiler accepts public/private/protected on the base class but it's useless as it breaks things.
Re: dsource considered harmful
On Sun, Jan 18, 2009 at 11:11 PM, Stewart Gordon wrote: > ... > Speaking of which, has anybody tried asking Brad for commit permission on > an abandoned project in order to revive it? > > Stewart. > I took over the MinWin project a long time ago, since its author, Ben Hinkle, had disappeared from the community, I tried reviving it for about half a year, with some success, but eventually I got tired of doing it alone, with little to no testers/users. So it's pretty dead now again... -Tomas
Re: Any chance to call Tango as Extended Standard Library
Andrei Alexandrescu wrote: > Don wrote: >> [snip] >> >> It means that any code which uses a library based on both Tango and a >> library based on Phobos will end up with two copies of all of the >> functions, and they'll have different name mangling etc. You end up >> with two incompatible Bigints, for example, even though they have >> identical code inside. > > Oh, I see. You want your library to be usable whether the end user > prefers Phobos or Tango. But then why not stick it into a namespace of > your choosing? Let's say your libraries are general enough to warrant > putting them in a common core, but then anyone who defines some library > don't have to go to the "core ombudsman" to add it to the common > namespace. They'd just create unique namespaces of their own. No? > > > Andrei I think he means this: let's say you're writing app A. A depends on libraries B and C. B depends on Phobos, and C depends on Tango. Both B and C happen to use BigInts or IO or anything else that isn't shared. All of a sudden, you've now got to link in TWO standard libraries instead of just one, each with potentially duplicated code. >From personal experience, the alternative isn't much better: writing code that switches between the two. I have an XML library that can use either Phobos or Tango. It does this by implementing all the calls it needs in a shim library, essentially using it's own standard library. It gets really fun when you need to implement some call that's trivial in one library, but really hard in the other. I remember having to build an IO layer so that both Phobos and Tango had the same semantics regarding EOF or something... Urgh. -- Daniel
Protection in BaseClassList: semantics undefined?
Hi, http://www.digitalmars.com/d/2.0/class.html In the grammar specification I read that a base class or interface name can be prepended a protection attribute. But I don't find a word about the semantics thereof... Can anyone tell (and update the docs)? Regards, Harry
Re: Any chance to call Tango as Extended Standard Library
Don wrote: Andrei Alexandrescu wrote: Don wrote: Andrei Alexandrescu wrote: IUnknown wrote: Regarding Phobos + Tango, the minimum I expect is things like containers, algorithm and common math stuff to be in one core module. This is already bound to be an issue because there is disagreement on how e.g. containers should look like (Java-style vs. STL-style). Which should be chosen? This naturally influences how algorithms are defined. Andrei The analogy with KDE vs Gnome doesn't seem valid to me -- most libraries will work regardless of which GUI library is chosen. Programmers can still rely on the Posix and C standard libraries. I agree. Can we work out the math stuff at least? There's no difference between Phobos and Tango there. All we need is an agreement on common module naming (eg, create core.math). That would be great. I don't think that's a major issue anyway. If I were you, to be compatible with today's state of affairs, I'd simply put in the makefile the code necessary for switching the module prefixes. It means that any code which uses a library based on both Tango and a library based on Phobos will end up with two copies of all of the functions, and they'll have different name mangling etc. You end up with two incompatible Bigints, for example, even though they have identical code inside. Oh, I see. You want your library to be usable whether the end user prefers Phobos or Tango. But then why not stick it into a namespace of your choosing? Let's say your libraries are general enough to warrant putting them in a common core, but then anyone who defines some library don't have to go to the "core ombudsman" to add it to the common namespace. They'd just create unique namespaces of their own. No? Andrei
Re: Any chance to call Tango as Extended Standard Library
Don wrote: Andrei Alexandrescu wrote: Don wrote: Can we work out the math stuff at least? There's no difference between Phobos and Tango there. All we need is an agreement on common module naming (eg, create core.math). That would be great. I don't think that's a major issue anyway. If I were you, to be compatible with today's state of affairs, I'd simply put in the makefile the code necessary for switching the module prefixes. It means that any code which uses a library based on both Tango and a library based on Phobos will end up with two copies of all of the functions, and they'll have different name mangling etc. You end up with two incompatible Bigints, for example, even though they have identical code inside. Interestingly, this might be less of a problem when using LDC. LLVM has an IPO pass to merge identical functions (opt -mergefunc).
Re: Overload by return type
BCS Wrote: > Hello dsimcha, > > > Just curious, why doesn't D, and why don't more statically typed > > languages in general, support overload by return type? I haven't > > exactly thought through all the pros and cons, but at first glance it > > seems like an incredibly useful thing. What's the catch that I'm > > missing? > > > > Off hand it's one more degree of freedom (and confusion) in trying to figure > out what type something is. > > int bar(char[] c) > int[] bar(char[] c) > > float baz(int i) > object baz(int[] i) > > auto z = baz(bar("what type is z")); > > float foo(); > object foo(); > > z = foo(); // what foo? > > Also for all other cases in D (and C, and C++, and C#, and ...) the semantics > of an expression is not dependent on what expression it is nested under. > Changing this could have far reaching consequences. Fortunately, D already has this bug http://d.puremagic.com/issues/show_bug.cgi?id=52
Re: Any chance to call Tango as Extended Standard Library
Denis Koroskin pisze: On Thu, 22 Jan 2009 09:18:52 +0300, Benji Smith wrote: IUnknown wrote: Agree. Which is why I said the problems you are facing seem to be non-technical. I'm suggesting that the D library developers should pick one and axe the other. *I* think what more important is to have one single set of containers in a single style rather than have two separate ones. There is going to be complaining for sure from the current developers, but in my opinion, the target of having a single standard library (with core and advanced modules to suit system/ app programming) is more important than having to make a difficult choice. Totally agree. While I personally prefer the Java-style containers, I'd gladly accept the STL-style containers if it meant unification of Phobos and Tango. Having druntime is nice, sure, but application-level code and high-level libraries will bake the container API into their public interfaces, and any code that uses both the Phobos and Tango libraries would have to perform a zillion tedious conversions. In my mind, the things that need a unified API are (in order of importance): 1. GC and TypeInfo 2. Data structures 3. Algorithms 4. String processing 5. Date & Time 6. IO Everything else (encryption, compression, sockets, regular expressions, could have a totally different API in Tango & Phobos and I wouldn't care much. Having a common runtime (GC and TypeInfo) is a neat trick, but pretty useless if the data structures and algorithms are entirely different. And, while I'm perfectly willing to accept either Java-style or STL-style containers, I'd also really appreciate it if the design anticipates and supports custom implementations (because I almost always end up implementing my own multimaps, multisets, circular queues etc) --benji I think believe we could take advantage of current state of both libraries in D2 - they are both incomplete and being redesigned to fit D2 better. We could revisit both Tango and Phobos, and clean them up by removing outdated modules and modules with same functionality. This will make Phobos really small and much easier to learn. On the other hand, Tango will continue providing all the extended functionality. Here is a list of Phobos modules that I believe could be safely removed: - crc32 and std.md5 - these should be deprecated in favor of tango.io.digest.Crc32 and tango.io.digest.Md5 Tango is better designed and has support for other algoriths (MD2, MD4, SHA256, SHA512, Tiger and more). See http://www.dsource.org/projects/tango/wiki/ChapterEncodingAndCrypto for details. - std.atomics - tango.core.Atomic is superior to it (std.atomics has nothing but CAS anyway). - std.base64 - deprecate in favor of tango.io.encode.Base64 - std.cover - is it supposed to be visible to user? Should it be in Phobos? - std.loader - deprecate in favor of tango.sys.SharedLib - std.bitarray - std.openrj - std.process - merge with tango.sys.Process - std.regexp - buggy, deprecate in favor of tango.text.Regex - std.socket, std.socketstream - deprecate in favor of tango.net.* - std.uni - deprecate in favor of tango.text.Unicode - std.uri - deprecate in favor of tango.net.Uri - std.xml - deprecate in favor of tango.text.xml.* - std.zip and std.zlib - deprecate in favor of tango.io.compress.* In almost *all* cases Tango has cleaner, faster and less buggy implementation of the same functionality. Other modules - does anyone use any of these: std.bitmanip std.bind std.boxer std.outbuffer std.stdint std.syserror std.system ? There are a lot of modules that only exist in Phobos because of some historical reasons or because Walter wrote it. Is it a sufficient reason for them to stay? They are no doubt useful sometimes, but are we going to put everything that is useful sometimes into Phobos? I believe it would be better for everyone to keep Phobos simple and prevent the two libraries from competing by separating the functionality. Once they don't compete anymore, users won't have to worry about what library to use how to stay compatible. Also my thoughts. Several months ago I send similar proposition to divide libraries responsibilities: - for Phobos - low level API - for Tango - higher level API Stuff which is in both libraries should be designed together by both teams. Andrei is talking about new design for IO in Phobos. Why not to prepare this new design together with Tango people? Some differences between philosophies of libraries should not stop merging. E.g. Phobos uses IO synchronized with C, but Tango is not. Why to divide libraries based on this? I think that there are cases where users would want one approach and also cases where they would want the other. IMHO standard library should have API allowing one or other approach depending on what user wants... So this difference is purely rhetorical... BR Marcin Kuszczak (aarti_pl) www.zapytajmnie.com - my christian site
Re: Any chance to call Tango as Extended Standard Library
On Thu, 22 Jan 2009 09:18:52 +0300, Benji Smith wrote: IUnknown wrote: Agree. Which is why I said the problems you are facing seem to be non-technical. I'm suggesting that the D library developers should pick one and axe the other. *I* think what more important is to have one single set of containers in a single style rather than have two separate ones. There is going to be complaining for sure from the current developers, but in my opinion, the target of having a single standard library (with core and advanced modules to suit system/ app programming) is more important than having to make a difficult choice. Totally agree. While I personally prefer the Java-style containers, I'd gladly accept the STL-style containers if it meant unification of Phobos and Tango. Having druntime is nice, sure, but application-level code and high-level libraries will bake the container API into their public interfaces, and any code that uses both the Phobos and Tango libraries would have to perform a zillion tedious conversions. In my mind, the things that need a unified API are (in order of importance): 1. GC and TypeInfo 2. Data structures 3. Algorithms 4. String processing 5. Date & Time 6. IO Everything else (encryption, compression, sockets, regular expressions, could have a totally different API in Tango & Phobos and I wouldn't care much. Having a common runtime (GC and TypeInfo) is a neat trick, but pretty useless if the data structures and algorithms are entirely different. And, while I'm perfectly willing to accept either Java-style or STL-style containers, I'd also really appreciate it if the design anticipates and supports custom implementations (because I almost always end up implementing my own multimaps, multisets, circular queues etc) --benji I think believe we could take advantage of current state of both libraries in D2 - they are both incomplete and being redesigned to fit D2 better. We could revisit both Tango and Phobos, and clean them up by removing outdated modules and modules with same functionality. This will make Phobos really small and much easier to learn. On the other hand, Tango will continue providing all the extended functionality. Here is a list of Phobos modules that I believe could be safely removed: - crc32 and std.md5 - these should be deprecated in favor of tango.io.digest.Crc32 and tango.io.digest.Md5 Tango is better designed and has support for other algoriths (MD2, MD4, SHA256, SHA512, Tiger and more). See http://www.dsource.org/projects/tango/wiki/ChapterEncodingAndCrypto for details. - std.atomics - tango.core.Atomic is superior to it (std.atomics has nothing but CAS anyway). - std.base64 - deprecate in favor of tango.io.encode.Base64 - std.cover - is it supposed to be visible to user? Should it be in Phobos? - std.loader - deprecate in favor of tango.sys.SharedLib - std.bitarray - std.openrj - std.process - merge with tango.sys.Process - std.regexp - buggy, deprecate in favor of tango.text.Regex - std.socket, std.socketstream - deprecate in favor of tango.net.* - std.uni - deprecate in favor of tango.text.Unicode - std.uri - deprecate in favor of tango.net.Uri - std.xml - deprecate in favor of tango.text.xml.* - std.zip and std.zlib - deprecate in favor of tango.io.compress.* In almost *all* cases Tango has cleaner, faster and less buggy implementation of the same functionality. Other modules - does anyone use any of these: std.bitmanip std.bind std.boxer std.outbuffer std.stdint std.syserror std.system ? There are a lot of modules that only exist in Phobos because of some historical reasons or because Walter wrote it. Is it a sufficient reason for them to stay? They are no doubt useful sometimes, but are we going to put everything that is useful sometimes into Phobos? I believe it would be better for everyone to keep Phobos simple and prevent the two libraries from competing by separating the functionality. Once they don't compete anymore, users won't have to worry about what library to use how to stay compatible.
Re: Templates and virtual functions
Walter Bright pisze: Setting aside the technical issues for the moment, I'd like to go back to the notion that structs are for compile time polymorphism and classes are for runtime polymorphism. Template functions are clearly in the compile time camp, and if you need compile time polymorphism in a class, perhaps the design should be seriously looked at to see if that's justifiable. That's not always true. I have similar case in my serialization library (Doost project) where template function is called in class to get information about class properties/values. Then, to support serialization from base classes I need to make virtual call to get most derived class. My point here is that there are cases where virtual template functions would be needed in classes. As to resolving the technical issue, put the instantiation of the template inside another virtual function: class foo { T nothing(T)(T arg) { // Non-virtual. return arg; } int virtual_nothing(int arg) { return nothing!(arg); } float virtual_nothing(float arg) { return nothing!(arg); } } The advantage of this is there is nothing new to learn. I was thinking about above design in my serialization library. As I already said it is needed for serialization of classes from base class reference (It's necessary to know most derived class to do proper serialization). Unfortunately such a design cause quite a big problem for users of such a library. Please let me explain below. I have following template in my libs: template Serializable() { void describeUdt(T)(T arch) { foreach(i, v; this.tupleof) arch.describe(this.tupleof[i], this.tupleof[i].stringof); } } Argument passed to function describeUdt is Archive, which is class, representing what type of output/input is used for serialization (JSon, Text, Binary etc) To make user class serializable is is just enough to put it as a mixin into user class. class UserClassA { mixin Serializable; } And now, to support serialization from base class pointer I played with following design: class UserClassA { mixin Serializable; void transportUdt(Archive arch) { describeUdt!(Archive)(arch); } } class UserClassB : UserClassA { mixin Serializable; void transportUdt(Archive arch) { describeUdt!(Archive)(arch); } } The problem here is that: 1. User of library will have to know all types of Archive template class (which is privately created by Serializer class). There are a lot of different possible classes which can be produced from Archive template class based on input/output stream type and based on type of archive. They should be unknown for user. 2. It is necessary to put functions transportUdt for every different Archive type into serialized class. It must be done by hand by user, as I don't see a way to make it automatically... Do you see any nice solution for above problem? I was thinking about registering somehow different Archive types during their instantiations and then automatically generating necessary functions transportUdt, but it doesn't seem to be possible currently... I would be happy to know about a good solution for this... REF: http://www.dsource.org/projects/doost/browser/trunk/doost/util/serializer Best Regards Marcin Kuszczak (aarti_pl) www.zapytajmnie.com - my christian site