March 30, 2012
On 2012-03-30 14:46:19 +0000, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> said:

> Destroy!

Since you're asking…

One thing the current system avoids is unresolvable symbols. If two symbol name clashes, you just qualify them fully and it'll always be unambiguous. For instance:

	.std.algorithm.sort(…)

Now, if std.algorithm becomes both a module and a package, you could have both a sort function and a sort submodule with no way to distinguish between the two, even when fully qualified. I think this is why D does not allow modules to have the same name as packages.

I understand that you try to work around this problem by inventing a .std.algorithm.package scope. Then you make it's content imported automatically inside the .std.algorithm scope for backward compatibility (and convenience). The problem is that if .std.algorithm.package contains a sort function and there is also a module called std.algorithm.sort, the fully-qualified name of that 'sort' module will become ambiguous. Moreover, whether the fully-qualified name .std.algorithm.sort is ambiguous or not depends on what modules were imported, which is not a very desirable behaviour.

So to make sure there is no unresolvable fully-qualified names, when importing std.algorithm.sort the compiler should make sure that no symbol called 'sort' already exist in the .std.algorithm scope (which includes the symbols in .std.algorithm.package and all other packages inside std.algorithm). This is clearly untenable.

- - -

I recognize the need. If I may, I'll propose something simpler:

1. allow both std/algorithm.d and std/algorithm/sort.d to exist
2. importing std.algorithm.sort will also implicitly import std.algorithm (if it exists) and std (if it exists)
3. if any symbol of std.algorithm clash with the std.algorithm.sort module name, you get an error when importing std.algorithm.sort.

Effectively, importing std.algorithm.sort becomes synonymous to importing std, std.algorithm, and std.algorithm.sort. This is what's needed to detect clashes in fully-qualified names.

The only issue now (beside a few more imports) is that if std.algorithm imports any of its submodule it becomes a circular import. That's usually fine in D, but not when you have module constructors.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

March 30, 2012
On Fri, Mar 30, 2012 at 05:35:25PM -0400, Jonathan M Davis wrote: [...]
> 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.
[...]

+1.

I also have my doubts about the wisdom of std.sort implicitly binding to std.algorithm.sort. It's nice syntactic sugar in the short term, but as Jonathan points out, it can cause headaches in the long term. I say we should hold off on that part of the proposal.


T

-- 
Microsoft is to operating systems & security ... what McDonalds is to gourmet cooking.
March 30, 2012
On 3/30/12 10:46 PM, 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).

Great. Large modules are my main complaint about D. :-)

If I correctly understand the second part (because I couldn't understand the text in the proposal until I read some comments here), then it makes sense. Is it like this?

sort(...) -> search sort in every module out there
std.sort(...) -> search sort in every module that's in the std package

If both std.algorithm.sort and std.path.sort exist, or something like that, then you would anyway get a clash so you'd have to fully qualify it.

But if std.algorithm.sort and foo.bar.sort and you'd import both:

import std.algorithm.package;
import foo.bar.package;

and you'd wanted to use both, then it could be convenient:

std.sort(...)
foo.sort(...)

Though I wonder if this indeed happens a lot. That's why I would wait until there's a real need for it. The main complaint people have is not having a way to import all files in a directory, which is the first point, but I never heard a complaint about the second point.

Also, I think it would make sense to change the first part to this:

* If the compiler sees a request for importing "foo.bar" and "foo/bar" is a directory, then automatically look for the file "foo/bar/package.d". *If it doesn't exist, automatically expand the import to import all files under that directory.* If both "foo/bar.d" and "foo/bar/" exists, compilation halts with an error.

That way you have convenience and safety. Most of the time people just put in package.d a list of all the files in that directory. Maybe sometimes (not sure) people restrict that list to some modules. And in those cases you can just restrict the list in package.d

Please, it's the year 2012. Compilers need to be smarter. Save people some typing time. You save them typing all the imports. But then you make them typing them in that pacakge.d file. Hmm...
March 31, 2012
I'm pretty impressed with the idea, and look forward to its implementation, but I do have one question.  How does this affect (if at all) the implicit "friend" relationship of declarations?  Since package "foo.bar" is treated as a single module, do the classes in "foo/bar/alpha.d" and "foo/bar/beta.d" have access to each other's private members?

I'm not sure whether I favor them losing or keeping their "friend" status.

----------
Chris NS
March 31, 2012
"Chris NS" <ibisbasenji@gmail.com> wrote in message news:ugopmohijjcnnrchuwbe@forum.dlang.org...
> I'm pretty impressed with the idea, and look forward to its implementation, but I do have one question.  How does this affect (if at all) the implicit "friend" relationship of declarations?  Since package "foo.bar" is treated as a single module, do the classes in "foo/bar/alpha.d" and "foo/bar/beta.d" have access to each other's private members?
>
> I'm not sure whether I favor them losing or keeping their "friend" status.
>

There's always the "package" access specifier.


March 31, 2012
On Saturday, 31 March 2012 at 06:39:07 UTC, Nick Sabalausky wrote:
> "Chris NS" <ibisbasenji@gmail.com> wrote in message
> news:ugopmohijjcnnrchuwbe@forum.dlang.org...
>> I'm pretty impressed with the idea, and look forward to its implementation, but I do have one question.  How does this affect (if at all) the implicit "friend" relationship of declarations?  Since package "foo.bar" is treated as a single module, do the classes in "foo/bar/alpha.d" and "foo/bar/beta.d" have access to each other's private members?
>>
>> I'm not sure whether I favor them losing or keeping their "friend" status.
>>
>
> There's always the "package" access specifier.

True, though it bears revisiting in its own right.  I've never been completely satisfied with the horizontal visibility, and would have preferred 'package' be defined as "visible within current package, *and subpackages* of the current."  But now I'm getting a bit off-topic.
March 31, 2012
On Sat, 31 Mar 2012 01:46:19 +1100, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Starting a new thread from one in announce:
>
> http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP16
>
> Please comment ...

We solved this issue in the Euphoria Programming language by introducing the concept of 'public include'.

The 'include' directive is similar to DPL's 'import' directive. Normally when a file (module) is included, its public identifiers are *only* visible to the including module and not further module up the include tree. However, if a module is 'public include'd then its public identifiers are set up *as if* they were actually declared in the including module rather than the included module.

Thus if Euphoria's module called datetime.e gets too large, we split it into, say two or three new modules and replace the code in datetime.e with corresponding 'public include' statements, thus making it a type of package definition. This means that existing application code does not have to be modified and future code can choose to include either the entire package called datetime.e or individual modules that go into making that package.

From the POV of a developer, creating a package out of what was a module is transparent. They do not even know or have to care in order to use it. There are no complicated access rules that can one day trip people up.

We made one tweak to the public identifier declaration though to cater for situations in which an identifier which was currently local to a module, but when moved to a new module when the original was transformed to a package, still had to be visible to the code in the package file but invisible to code including the package. We created the 'export' qualifier on an identifier declaration to signal such an item.

Original module code ...

  function to_seconds(datetime x)  /* A local function to the module */

  public function local_to_gmt(datetime x) /* A publicly exposed function */

New module code ...

  export function to_seconds(datetime x)  /* A function visible to the package file only */

  public function local_to_gmt(datetime x) /* A publicly exposed function */


This means that application that include the package datetime.e will not see to_seconds() but code in the datetime.e will see it, and local_to_gmt() will be seen by the application code and the package code.


-- 
Derek Parnell
Melbourne, Australia
March 31, 2012
On 03/30/2012 11:35 PM, Jonathan M Davis wrote:
> 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

+1. That is even better than treating the package module specially.
March 31, 2012
On Friday, 30 March 2012 at 14:46:16 UTC, 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

Hooray! I was loudly complaining about this issue for years. I'm glad this is finally going to be taken care of.

1. Regarding naming - as others mentioned it's inconvenient for sorting. How about changing the file extension instead of the name? e.g have a "algorithm.package" instead of "algorithm.d"? The compiler could even ignore the name of the file as long as it has the proper extension - check for existence of "*.package".
The compiler should enforce that there's at most one such package file to prevent ambiguities - regardless of the chosen naming scheme.

2. Regarding documentation - I'd encourage (via a D style guideline) putting the overview of the package in this file. A tool such as Ruby's codnar would nicely compliment the reference generated by DDoc. see https://www.ruby-toolbox.com/gems/codnar for details.

3. std.algorithm should be deprecated and eventually removed. All code *is* essentially algorithms and as such importing this module makes as much sense as doing:
import code; // generic much?

4. regarding the look-up rules - I'm unsure about this part of the proposal. Others already voiced concerns about issues this might bring.
March 31, 2012
On Sat, 31 Mar 2012 13:06:36 +0200, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 03/30/2012 11:35 PM, Jonathan M Davis wrote:
>> 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
>
> +1. That is even better than treating the package module specially.

That already works, doesn't it?