As much as I'm used to working with entire libraries of free functions, they do tend to create problems if identifiers happen to overlap between unrelated libraries. To side-step this "namespace pollution" would you (or many others?) be adverse to using static methods of a class as opposed to free functions?

IMO, all the namespaces should tread lightly and leave as small a footprint on its containing namespace as possible, due to the flat-alias nature of "import".

I'm starting to think that this one really needs to be nipped in the bud, and only Walter can do it. Between the way the import statement pulls symbols into the current scope, and the nature of the alias statement, name resolution in D is proving to be quite frail. I think the fact that we're considering going through all these contortions to play nice with it is pretty compelling evidence to this effect.

Failing this, I think the "import into a struct" idiom is probably the best way to deal with these issues. It's a relatively simple way to resolve the problem, but it puts the burden on the programmer, and not Phoenix. I still think this is preferable because taking the Java-static-class basically amounts to making the common cases verbose and inconvenient, and all to avoid potential conflicts.

eg

Code:

struct std {
struct string {
import std.string;
}
}

This forces all references to std.string to be qualified, a la Python. (I just wish it was a bit prettier )

Second, I think a string class is a really bad idea. D doesn't allow any implicit conversions, which basically means that any such class is doomed to be even more ragged than std::string._________________"Complacency is a far more dangerous attitude than outrage." - Naomi Littlebear

Last edited by andy on Fri Aug 27, 2004 6:30 pm; edited 1 time in total

Maybe we could have a package called phoenix.oo.* with class wrappers for frequently clashing modules? Then, you could import phoenix.oo.string and import phoenix.oo.etc.unicode and access them with static class methods. But if you're only or mostly using one or the other, you can use them the quick way.

That's just crazy enough to work. It's an idea, but I'm not too keen on it myself.

On a slightly OT note, here's a compromise I've worked up. Oddly enough, it has a lot to do with the "typedef block" proposal I posted to the DNG over a month ago.

What if we do this, and try to treat the humble char[] almost like a class:

Alias just happens to be strong enough to sort through the overload resolution for us without causing ambiguities.

We can have it both ways: free functions that can be used as an "extended primitive" type (almost a class) or in this case "char[] = String". If UString becomes a class instead of a simple wchar[], then the two won't behave as much the same and there will be fewer collisions.

This doesn't do away with the 100-and-1 toString() overrides which may or may not be a bad thing. "int i; i.toString()" is kind of nice to be able to do.

BTW, if we still have more momentum on the topic of how to compose the string library, we should probably move it to another thread.

jcc7 wrote:

Another idea is since the string vs. unicode issue will surely be a common challenge, can't we create a "unification" module that uses alias to choose the unicode version when there's a clash and import the non-overlapping portions from each module. Maybe it's a crazy idea, but I think it might work.

Personally I'd like to discourage writing "glue modules" all over the place. Since we're writing a library that is free from hangups and quirks (unlike Phobos.. D is outgrowing it), lets do it right the first time.

Keep those ideas coming! We're doing great in this thread._________________-- !Eric.t.Anderton at gmail

Personally I'd like to discourage writing "glue modules" all over the place, of course. Since we're writing a library that is free from hangups and quirks (unlike Phobos.. D is outgrowing it), lets do it right the first time.

I wouldn't think we'd need many "glue modules". Perhaps just one glue module to get old-fashioned strings stuff and new unicode stuff to play nice together. If we could solve 95? of the problems with one glue module, would that be enough benefit to avoid wrapping everything else in either classes or structs?

I'm warming up to the wrapping ideas, but it still seems terribly redundant.

String doesn't have to be ragged if it's included with the standard library, which comes with the compiler (which Pheonix hopefull will)

Such a class can never be usable where a char[] is expected, or vice versa.

"String s = new String("hello!");" is every bit as ugly as "char* ch = malloc(10); strcpy(ch, "hello!");". Both are dead giveaways that strings are second-class citizens of the language.

Unless a string type is added to the core language, char[], wchar[], and dchar[] are here to stay, and we'll get a lot more done if we don't fight it.

pragma's suggestion that we define aliases is a great idea. D's funky pseudo-array-method syntax lets us have our cake and eat it too._________________"Complacency is a far more dangerous attitude than outrage." - Naomi Littlebear

We may also consider what tools and bits that should accompany a binary distribution. Perhaps some standard dll and application stubs along with example makefiles would ease app development. Also, I'm assuming that portability between Win32 and linux is a given... when/how/if are we going to tackle other platforms like BSD and OS X?

We'll need a clean version setup for the OS-dependent bits. I've got access to both BSD and OS X machines if that's any help, though my OS X access is limited (it's my wife's comp ). Still, the back-end code should be fairly consistent across all Unix-like platforms, though I'm not sure offhand if OS X has full POSIX support (I imagine it does?) and multiplexed i/o will be different for every platform (assuming we ever want to develop that).

I wouldn't think we'd need many "glue modules". Perhaps just one glue module to get old-fashioned strings stuff and new unicode stuff to play nice together. If we could solve 95? of the problems with one glue module, would that be enough benefit to avoid wrapping everything else in either classes or structs?

This is the only instance where I think collisions may realistically occur, and for good reason. Perhaps we could control this with a version statement? Give the user the option of pulling in the standard ASCII-oriented routines or more advanced Unicode stuff. It would be one or the other for any given project. But assuming we did this, would there be problems with static libraries or DLLs, and would it be safe to tell the user it's something he's just going to have to deal with?

-String. I'm so sick of these std.string functions. Let's do two things: 1) Get AJ's ICU port and add whatever methods are necessary make it a viable replacement for std.string. 2) Make a String class that will wrap the functions. If it uses ICU, it shouldn't be too hard to make it completely Unicode compliant.

Actually, ICU does contain a class called UnicodeString which has some basic string functionality. The first port won't have this as such, because I'm just gonna wrap the C API (and C doesn't have classes), but once that's done, the D API (which will be similar to the Java API) should resurrect it.

demmegod wrote:

It would also be nice if there were some way to make it implicitly convertable to/from (d/w)char arrays, but I don't think that's currently possible with the compiler.

std.loader is not compiled into phobos on linux. Can you add std.loader to this project and then compile it into the linux library that will be distributed with phobos rising?

that's all bye.

You can bet that one of my first informal contributions to the project is going to be a strong set of library management classes and stubs, similar to what I have now for DSP. I don't fault loader.d one bit, but I think the design could be improved upon. Plus, Phobos is lacking as a developer kit simply because there are no standard dll stubs to use._________________-- !Eric.t.Anderton at gmail

My opinion is that the decision about whether to use classes or free functions should be based on whether the 'thing' stores any state. If it stores state then use a class, otherwise use free functions.

If the state is a single thing i.e. a handle, an int, etc then you can use free functions or a class depending on which is better conceptually eg..

Handle h = loadLibrary(..);
freeLibrary(h);

or

class Library {
Handle h;

bool load(char [] name) {..}
void free() {..}
}

in the above you can use the class as 'auto' so making it a class is perhaps the best approach. I think you could do other cool things with a class like storing a list of methods loaded from the library, perhaps with an AA?

I don't think choosing OO or non OO is the path to take but rather to choose the best approach per situation/module. If it can be done best as free functions, then do it that way, you can always add a additional class wrapper for those who want pure OO. The best of both worlds IMO.

The whole namespace/import/alias problem...

"There was an example recently where the module-level ('C' style) toString() methods of std.string 'eliminated' a superclass toString() from being resolved."

Doesn't the above only occur if you use an 'inner' import?

The import thing has only bothered me once, and it was a case of having to specify the full symbol name at a time where I thought it should be able to "work it out" for itself eg.

I think this boils down to the name resolution rules looking in the local scope before the imported scope, finding a toString locally, and deciding I mean't that one rather than looking for a "better" one.

What are the other issues.. can someone come up with a list of them?

So far I dislike the import into a struct idea as I dislike having to specify the complete symbol all the time. I dislike the idea of making everything a class, I think multi-paradigm approach is better.

So far I dislike the import into a struct idea as I dislike having to specify the complete symbol all the time. I dislike the idea of making everything a class, I think multi-paradigm approach is better.

I think I agree.

It should never actually be necessary anyway. Fully qualifying identifiers will work whether or not the import is placed in a struct, and all it takes to resolve overload ambiguities is an alias.

For instance, your example could be written as

Code:

import std.string;
import std.stdio;

/*
* Pull std.string.toString into this scope, which puts it on equal footing with
* the toString defined in this module. Overload resolution will work as
* expected now.
*/
alias std.string.toString toString;