This is a sub issue of #13831, #14790 and #14799.
We're still deciding whether import statements should enable only qualified
access (and have controls over that) or whether they should be able to also
enable unqualified access. If we follow the latter path, a few syntax strategies
have been thrown around:
import M only x;, import M only x, y;import M.x;, import M.{x, y};import M only x local;, import M only x, y local;I'm currently feeling strongly in favor of option 2 for its brevity and lack of reliance on the only keyword (which, as @gbtitus argued, doesn't really suggest anything relating to "unqualified" to me). I think the asymmetry with use statements is arguably a strength since I think import statements are being introduced to contrast in purpose and effect with use.
It's not really called out in the issue description but one design direction we could go is to rely on use for unqualified access and have import only handle qualified access for modules. I'm not really sure I could articulate reasons to do that or not do that though. @bradcray - can you?
I also like the import M.x form, generally, if we want import to have such a feature.
Hi Michael 鈥斅燭he reasons that I didn't seriously consider that approach is due to:
(a) Python and Rust each supporting forms that enable unqualified access (so if we think of them as motivators for import, it would seem unfortunate to take away that capabiity?), combined with:
(b) wanting programmers (who chose to) to be able to live in an import-only world without feeling crippled (where I would think being forced to not be able to create shorthands for such things as being crippling.
But just to play with the idea, would that suggest that import M; or import M.N.O (where M, N, and O are all modules) are the only kinds of things that import could express? (I think you said in our deep-dive that you didn't think import M only x; as a means of permitting M.x but not M.y didn't make sense, which is why I'm wondering that?)
Python and Rust each supporting forms that enable unqualified access
Python and Rust have module systems that allow both qualified and unqualified access. Is it so bad if we use a different keyword for unqualified access than qualified? We would still support both as well.
wanting programmers (who chose to) to be able to live in an import-only world without feeling crippled
I believe that some programmers would like to live in a qualified-access-only world. Such programmers wouldn't be able to use imports with qualified access either, presumably. I don't think that programmers with this viewpoint are objecting literally to the syntax of use but rather to its tendency to make too many symbols visible. I think such programmers also would not want to use import M.* (supposing we had such a feature).
Now, such programmers might be OK with something like import M.x to bring in a specific symbol or use M only x. It's not clear to me that they would care that it was import vs use giving them this capability.
However, there is a potential difference between these two - namely, whether or not they bring in the symbol M. Today, use M only x also makes M available. However, I think that we need some way of expressing something to bring in specific (non-module) symbols for unqualified access - without bringing in the module - in order to enable re-exports (issue #13979).
We have brought up these possibilities for that:
use does not bring in the symbol for the module used (#13978)use does bring in the symbol for the module used but doesn't make it available transitively (https://github.com/chapel-lang/chapel/issues/13979#issuecomment-532897747 )import has an unqualified access form that does not bring in the module (e.g. import M.x in this issue)use M as _ only x avoids bringing in the moduleMaybe when the purpose is clear an the options are in front of us it will be easy to explain why we should go with one or the other of these.
But just to play with the idea, would that suggest that import M; or import M.N.O (where M, N, and O are all modules) are the only kinds of things that import could express?
Yes, that is what I would expect. Programmers would write use M only x rather than import M.x, say.
one design direction we could go is to rely on use for unqualified access and have import only handle qualified access for modules. I'm not really sure I could articulate reasons to do that or not do that though.
Pros:
Cons:
I believe that some programmers would like to live in a qualified-access-only world. Such programmers wouldn't be able to use imports with qualified access either, presumably. I don't think that programmers with this viewpoint are objecting literally to the syntax of use but rather to its tendency to make too many symbols visible. I think such programmers also would not want to use import M.* (supposing we had such a feature).
I agree with this thinking
I believe that some programmers would like to live in a qualified-access-only world.
I don't think I've talked to any programmers asking for that perspective.
I believe that some programmers would like to live in a qualified-access-only world.
I don't think I've talked to any programmers asking for that perspective.
Sounds like I'm confused about the purpose of this effort.
The import epic (#13119) says:
As a Chapel programmer coming from Python who's sensitive to protecting my namespaces, I would like Chapel to support an import statement similar to Python's and opposite to Chapel's use. That is, by default, no symbols would be available without full qualification by default. Thus, import M; would be similar to use M only; or use M except *; in Chapel today.
So, coming back to this:
wanting programmers (who chose to) to be able to live in an import-only world
Why would a programmer want to live in an import-only world? Is it because they only want to think about Python's import rules which they are already familiar with? Or is it because they want a module system with default behavior that is less eager to bring in lots of symbols (so that they have to opt in to getting specific symbols, say), to reduce the chances of namespace problems in the future? Or is it that they don't like the use syntax for some reason? Or something else?
Sounds like I'm confused about the purpose of this effort.
This gets back to the question I asked in the deep-dive about what we think our motivation for import is, since I think deciding on that would help with a lot of the technical questions. Some options might be (and you could pick more than one):
useuse for some modes of programming, but not alluse to be completeI'm currently leaning toward the second bullet as being my main motivator in making decisions and am using bullet 4 as a sub-motivator, such that for a team that wanted to encourage a particular "safe house style" code containing only import might be considered to meet their goals.
I don't view a world in which import M.x; permits unqualified access to x to be inherently unsafe because the programmer is being very explicit about what they're bringing into scope. I'm currently advocating that we not support import M.*; or something to the effect of import M except x; for similar reasons (it's less safe because you're not stating what you expect to get from M).
It would seem odd to me if use M; prevented M from being available to the scope by default. For example, in the following example:
use M only x;
writeln(x); // OK: this refers to M.x
writeln(M.x); // compiler error: what the heck is M?
it seem really weird to me for the compiler to suddenly not seem to recognize M when it did just a few lines above in the use statement. It also seems arbitrarily (and slightly cruel) not to permit x to be referred to the more precise / fully qualified manner. (I also really wouldn't want us to have to update existing code to make this change). It's for these reasons that I think use M; should continue to permit qualified access through M and prefer use M as _; as the approach for the "avoid re-exporting M" scenario for use.
Similarly, if the only thing import could do was permit you to start referring to a module, it seems pretty toothless as a new keyword / statement, and like a pretty heavyweight mechanism to permit referring to module names.
In addition, it seems like a fairly arbitrary dividing line for import M.N; where N is a module to permit N to be referred to in an unqualified way, but not to have import M.N.x where x is a variable permit x to be.
So, to me, the import M.N.{x,y,z}; form has the benefits of:
use would likely not be required in their programs)provide a feature that's safer / more defensive than use
I think this is a reasonable goal and I'm comfortable with proceeding along the lines of import M.N.{x,y,z} / #14790.
I think I can safely say that the answers to this issue are "Yes" and "using either . for a single symbol or .{} for a list of symbols"
Most helpful comment
This gets back to the question I asked in the deep-dive about what we think our motivation for
importis, since I think deciding on that would help with a lot of the technical questions. Some options might be (and you could pick more than one):useusefor some modes of programming, but not alluseto be completeI'm currently leaning toward the second bullet as being my main motivator in making decisions and am using bullet 4 as a sub-motivator, such that for a team that wanted to encourage a particular "safe house style" code containing only
importmight be considered to meet their goals.I don't view a world in which
import M.x;permits unqualified access toxto be inherently unsafe because the programmer is being very explicit about what they're bringing into scope. I'm currently advocating that we not supportimport M.*;or something to the effect ofimport M except x;for similar reasons (it's less safe because you're not stating what you expect to get fromM).It would seem odd to me if
use M;preventedMfrom being available to the scope by default. For example, in the following example:it seem really weird to me for the compiler to suddenly not seem to recognize
Mwhen it did just a few lines above in theusestatement. It also seems arbitrarily (and slightly cruel) not to permitxto be referred to the more precise / fully qualified manner. (I also really wouldn't want us to have to update existing code to make this change). It's for these reasons that I thinkuse M;should continue to permit qualified access throughMand preferuse M as _;as the approach for the "avoid re-exporting M" scenario foruse.Similarly, if the only thing
importcould do was permit you to start referring to a module, it seems pretty toothless as a new keyword / statement, and like a pretty heavyweight mechanism to permit referring to module names.In addition, it seems like a fairly arbitrary dividing line for
import M.N;whereNis a module to permitNto be referred to in an unqualified way, but not to haveimport M.N.xwherexis a variable permitxto be.So, to me, the
import M.N.{x,y,z};form has the benefits of:usewould likely not be required in their programs)