View mode: basic / threaded / horizontal-split · Log in · Help
March 30, 2012
Re: DIP16: Transparently substitute module with package
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
March 30, 2012
Re: DIP16: Transparently substitute module with package
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
March 30, 2012
Re: DIP16: Transparently substitute module with package
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?
March 30, 2012
Re: DIP16: Transparently substitute module with package
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
> _bad_ idea.

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


Andrei
March 30, 2012
Re: DIP16: Transparently substitute module with package
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!
March 30, 2012
Re: DIP16: Transparently substitute module with package
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.
March 30, 2012
Re: DIP16: Transparently substitute module with package
"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.
March 30, 2012
Re: DIP16: Transparently substitute module with package
"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.
March 30, 2012
Re: DIP16: Transparently substitute module with 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
March 30, 2012
Re: DIP16: Transparently substitute module with package
"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
Top | Discussion index | About this forum | D home