View mode: basic / threaded / horizontal-split · Log in · Help
On Friday, March 30, 2012 20:06:57 Andrej Mitrovic wrote:
> On 3/30/12, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> > Destroy!
>
> "That means a program that imports std.algorithm may use "std.sort"
> for the symbol "std.algorithm.sort"."
>
> That's quite interesting. Would that also mean that you could do:
> import std.algorithm; // has indexOf
> import std.string; // has indexOf
> void main() {
> string.indexOf("foo", "foo"); -> std.string.indexOf
> }

No, I don't think so. If I understand the proposal correctly, it would enable
std.indexOf (which doesn't help you at all in this case), not string.indexOf.
It's trying to make it so that you can treat a symbol in a sub-module as it
were in a higher module, and string.indexOf doesn't help with that at all.

- Jonathan M Davis

On Friday, March 30, 2012 12:15:44 Brad Anderson wrote:
> On Fri, Mar 30, 2012 at 12:06 PM, Andrej Mitrovic <
>
> andrej.mitrovich@gmail.com> wrote:
> > On 3/30/12, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> > > Destroy!
> >
> > "That means a program that imports std.algorithm may use "std.sort"
> > for the symbol "std.algorithm.sort"."
> >
> > That's quite interesting. Would that also mean that you could do:
> > import std.algorithm; // has indexOf
> > import std.string; // has indexOf
> > void main() {
> >
> > string.indexOf("foo", "foo"); -> std.string.indexOf
> >
> > }
>
> I was actually kind of surprised when I found out this doesn't work. It
> seems so natural to resolve ambiguity using as little context as necessary.

It would certainly be desirable in some cases, but I believe that the reason
that it doesn't work is due to the ambiguities that it would create. I'd have
to go dig up old discussions on it though to remember all of the details.

alias is supposed to solve the problem, but it doesn't really work all that
well for it, since private doesn't hide symbols, it only makes them
inaccessible (just like with C++). So, creating aliases in a module causes
problems in other modules that import that module, even if the aliases are
private. There are definitely some folks pushing for private to actually start
hiding symbols (IIRC, there's even a pull request for it), but I don't know
what the odds of convincing Walter are. If/Once that happens, alias will
actually become usable for this sort of situation, and the inability to do
string.indexOf won't be as big a deal.

- Jonathan M Davis

On Friday, 30 March 2012 at 18:39:44 UTC, Jonathan M Davis wrote:
> I'd propose that we make it so that if a module publicly
> imports another
> module, then you could treat it as if it were in that module.
> So, because
> std.datetime.package publicly imports std.datetime.systime, you
> could use
> std.datetime.SysTime instead of std.datetime.systime.SysTime.

I'm not sure if that's a good idea. I'd prefer a new kind of
import statement, perhaps something like:

// module std.datetime.package
alias import std.datetime.systime;

which is similar to a public alias of everything in that module?

On 3/30/12 1:39 PM, Jonathan M Davis wrote:
> However, I'm very nervous about the second part. e.g. std.sort instead of
> std.algorithm.sort seems like a bad idea to me. It increases the odds of name
> conflicts for little benefit.

Example?

> Not to mention, it'll make it a lot more confusing
> to find what modules stuff is actually in if people start doing stuff like
>
> std.sort(arr);
>
> In the case of sort, you may know where it's from - particularly since it's so
> common - but the less well-known the function is, the less likely that is at
> all obvious where it comes from, and if you're dealing with 3rd party
> software, then it wouldn't be at all obvious. For instance, how would you know
> that party.foo is really party.bar.foo? You wouldn't.

Why should you?

> Being so lax about
> importing could really harm code readibility (and maintainibility, since it
> increases the odds of name clashes). So, I'm inclined to say that that is a

Maybe if you produce a solid example, I'd be convinced.

Andrei

My comments:

1. My first impression was that using "foo/bar/package.d" instead of
"foo/bar.d" seemed a bit odd and messy. But I realize now that cleverly
solves the issue where "foo/bar.d" would be considered to be inside a
different package from "foo/bar/*.d". So I like that. Personally, I think I
would have gone with "foo/bar/_.d" as that sorts much, much better, but
naming debates can go on forever, and I can live with "package.d"

2. I don't understand any of this:

-------------------------------------------
When looking up the symbol "foo.bar.baz", currently an exact match is
needed. However. when looking up ".baz" or simply "baz", a flexible lookup
is used that has many advantages (less verbose, hijacking detection etc).
Therefore we think similar flexibility should be imparted to "foo.bar.baz",
as follows:

If a qualified symbol "foo.bar.baz" appears in code, the compiler considers
"foo.bar" a prefix that sets the starting point of the lookup, and then
proceeds with looking up "baz" from that starting point. That means a
program that imports std.algorithm may use "std.sort" for the symbol
"std.algorithm.sort".
-------------------------------------------

I *do* understand "a program that imports std.algorithm may use "std.sort"
for the symbol 'std.algorithm.sort'", and I think that's a good idea. It
solves a problem I hadn't even thought of. But I don't understand that stuff
I quoted above. Perhaps you could reword/clarify?

3. Other than that stuff, I'm very much in favor of this. I'll have some of
that!

On Friday, 30 March 2012 at 18:15:57 UTC, Brad Anderson wrote:
> On Fri, Mar 30, 2012 at 12:06 PM, Andrej Mitrovic <
> andrej.mitrovich@gmail.com> wrote:
>
>> On 3/30/12, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>> > Destroy!
>>
>> "That means a program that imports std.algorithm may use
>> "std.sort"
>> for the symbol "std.algorithm.sort"."
>>
>> That's quite interesting. Would that also mean that you could
>> do:
>> import std.algorithm;  // has indexOf
>> import std.string;  // has indexOf
>> void main() {
>>    string.indexOf("foo", "foo"); -> std.string.indexOf
>> }
>>
>>
> I was actually kind of surprised when I found out this doesn't
> work.  It
> seems so natural to resolve ambiguity using as little context
> as necessary.

Ya that was the behavior I expected as well. Would be great if it
worked like that. Just back trace the reference until the
ambiguity is resolved.

// -----

Also, I'm probably missing something here, but I never understood
why importing a package doesn't work like it does in
Actionscript/Java/others...

import foo.bar.*; // everything
import foo.bar.all; // custom

That makes a lot of sense to me.

"Timon Gehr" <timon.gehr@gmx.ch> wrote in message
news:jl4jmg$2j1r$1@digitalmars.com...
>
> I don't really like the second one.
>
> 1. It is an over-general solution, because it does not solve a general
> problem.
>
> Maybe it would be better to just interpret foo.bar.baz as
> foo.bar.package.baz if foo.bar is a package that has been imported via the
> foo.bar.package rewrite?

That occurred to me, and I thought about proposing the same thing you're
suggesting, but on second thought I wasn't so sure:

If I need to disambiguate between "std.algorithm.find" and
"foo.bar.baz.find", it might be nice to be able to just say "Meh,
just...that one in Phobos, ie 'std'". Or "Just go with that 'foo' one".

I could go either way, really.

"Robert Clipsham" <robert@octarineparrot.com> wrote in message
news:jl4l5t$2m62$1@digitalmars.com...
> On 30/03/2012 15:46, Andrei Alexandrescu wrote:
>> Starting a new thread from one in announce:
>>
>> http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP16
>>
>> Please comment, after which Walter will approve. Walter's approval means
>> that he would approve a pull request implementing DIP16 (subject to
>> regular correctness checks).
>>
>>
>> Destroy!
>>
>> Andrei
>
> The proposal doesn't say what happens when package.d is not found but
> foo/bar/ exists.
>
> Given that a lot of people will just use public import foo.bar.*; in that
> file, would it make sense for package.d missing to imply import foo.bar.*?
> That would save typing out every single file in there. Of course it would
> also be annoying if you wanted to import everything except one file, as
> you'd then have to type out every single import anyway.
>

That would effectively be the same as Java's "import foo.*" and a lot of
people have issues with that.

> The other option is to error, which is probably a more sane option.
>

That's what I'd suggest doing. Just treat it like importing any other
missing package.

On Friday, March 30, 2012 14:33:58 Andrei Alexandrescu wrote:
> On 3/30/12 1:39 PM, Jonathan M Davis wrote:
> > However, I'm very nervous about the second part. e.g. std.sort instead of
> > std.algorithm.sort seems like a bad idea to me. It increases the odds of
> > name conflicts for little benefit.
>
> Example?

std.sort works because there's only one sort. If there are two, you get a
conflict (e.g. if you had std.path.sort which sorted paths in some path-specific
manner). If std.path.sort existed now, then std.sort wouldn't work, and you'd
be forced to specify std.algorithm.sort or std.path.sort, and that's fine. It
would be similar to having to specify std.algorithm.indexOf when you've
imported both std.string and std.algorithm. But the problem is when
std.path.sort is added _later_.

All of a sudden, code which used std.sort and worked is now broken. The
problem does currently exist in that if we added indexOf to another module -
say std.array - then code which imported either std.string or std.algorithm as
well as std.array would break with the addition of std.array.indexOf, but your
proposal makes it worse. Not only does it provide another way in which adding
a function could result in conflicts when existing code is recompiled, but it
makes it so that if you add any function anywhere in the _entire standard
library_ which has the name as an existing one, you get a conflict (if anyone
uses std.x rather than x or the full import path).

D does a good job of providing ways to fix name conflicts, but it doesn't do a
good job of preventing them when adding new symbols to a library (primarily
because it doesn't use static imports by default), and your proposal makes
that part of the problem worse. If std.x were to become common practice, then
any time that you added a symbol to a library when that symbol was already
used by another module, you'd create conflicts (combined with the fact that
private doesn't hide symbol names but merely makes them inaccessible, this
could result in a lot of symbol name conflicts).

> > Not to mention, it'll make it a lot more confusing
> > to find what modules stuff is actually in if people start doing stuff like
> >
> > std.sort(arr);
> >
> > In the case of sort, you may know where it's from - particularly since
> > it's so common - but the less well-known the function is, the less likely
> > that is at all obvious where it comes from, and if you're dealing with
> > 3rd party software, then it wouldn't be at all obvious. For instance, how
> > would you know that party.foo is really party.bar.foo? You wouldn't.
>
> Why should you?

Do you know what the foo function does? If you don't, you're going to have to
look it up. And if you don't know what module it comes from, you can't do
that. You also have to know where foo is from if a foo function is added to
another module and causes a conflict, because you're going to have to give the
full import path to actually use it. That's currently true with just bare foo
as well, but party.foo gives the illusion of specifying where foo is from
without actually specifying where it's from. At least right now, if foo is
used with its import path, you know that that's actually its import path.

Also, what happens if we want to add a module named sort later? The fact that
people are using std.sort means that adding std.sort as a module will break
code. Granted, it's not very likely that we're going to add a module named
sort, but there are plenty of other symbol names that it could happen with.
But then again, if we decided to provide a module with all of the major sort
algorithms, then maybe we _would_ create a module named std.sort. Just because
we don't see a need now doesn't mean that we won't later. In either case, by
allowing std.x where x is a symbol in any sub-module of std, you're going to
create conflicts any time that you add a module which has the same name as an
existing symbol anywhere in the library.

> > Being so lax about
> > importing could really harm code readibility (and maintainibility, since
> > it
> > increases the odds of name clashes). So, I'm inclined to say that that is
> > a
> > _bad_ idea.
>
> Maybe if you produce a solid example, I'd be convinced.

Well, as I've pointed with a few examples here, your proposal will increase
the chances of adding symbol conflicts any time that a symbol is added to a
library all just so that you can do std.algorithm.sort instead of
std.algorithm.submodule1.sort once sort has been moved to
std.algorithm.sumodule1. And we could make it possible to do
std.algorithm.sort without adding all of those possible conflicts.

The simplest solution would simply be to make it so that if std.algorithm.sort
is used, and std.algorithm is a package with a std.algorithm.package module,
then the compiler looks in all of the sub-modules of std.algorithm to find
sort. That solves the problem right there without increasing the odds of
symbol conflicts across the entire library like your proposal does.

But personally, I like the idea of making it so that publicly imported symbols
can be accessed as if they were in the module that publicly imported them
(with package.d being treated as if it had the same name as the package that
it's in). That's essentially how it already works except when specifying the
full import path for a symbol. And that way, you can specify in
std.algorithm.package.d exactly what you want to be imported when
std.algorithm is imported (including using : to restrict it to specific symbols
in a module), and only those symbols will be treated as if they were part of
std.algorithm - both for importing purposes and when specifying the import
path when using a symbol. The library maintainer then has control over which
symbols get used with which import paths.

- Jonathan M Davis

"Andrej Mitrovic" <andrej.mitrovich@gmail.com> wrote in message
news:mailman.1240.1333130858.4860.digitalmars-d@puremagic.com...
>
> Still this is one of the few proposals I like. My only caveat is the
> comment: "except the file is not allowed to use the "module"
> declaration.". Wouldn't it be better if we explicitly declared a
> module as a package instead? In foo\bar\package.d:
> package foo.bar;
>
> Since the "module" declaration must be on the first line (or second
> line after shebang), you could special-case DMD to allow the package
> keyword to be used here. I know D likes to abuse a keyword for
> multiple things (hello Mr. Static!), but I think we could live with
> it.

Or maybe just require the module name ends with ".package"

1 2 3 4 5 6