-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove require, import, and maybe importall and merge into using #8000
Comments
We'd need the |
|
|
To bind This could be This also removes the distinction between bringing something into scope and making it available for method extension. I personally think that's a good thing and makes the module system more understandable, but I wanted to make sure we brought it up. |
There is a strong case to be made that a construct that makes all of a module's exported bindings available should make them soft ( But if you have explicitly listed the identifiers you want to import, then there is never a reason to give a soft binding. Either you are not going to define new methods of an identifier, in which case hard and soft bindings have identical behavior, or you are going to define new methods of it, in which case a soft binding is equivalent to no binding and if you want that behavior you should just remove the identifier from the list. So, in short, I like @StefanKarpinski's proposal. Conceptually we need both hard and soft bindings, but we can get all useful behaviors with a single keyword. |
I see your point. In that case I like your proposal that The empty trailing |
The trouble with the empty trailing colon is that we currently look for a name on the next line – in other words |
Related: #4600 |
I know that current Julia practice is to import everything into the I also think that the current overloading of using Foo and using Foo.Bar is |
I think in Stefan's proposal, this is addressed with using Foo: Foo On Thursday, August 14, 2014, toivoh [email protected] wrote:
|
@kmsquire but what then happens if there is a Foo module inside of the Foo module? That's unfortunately ambiguous. |
That's a design error (and causes a warning), so it doesn't matter |
I like the version proposed by @ssfrr above the best. |
Is there an underlying convention that packages have one and only one module entry point? -- To I ask b/c I am wondering if
would import from |
Yes, packages, package entry points, and modules are expected to be one-to-one. You can break this convention if you need to, but there's not much need for that since modules are just for naming and aren't functional units. The idea that you're bringing up is #4600 except the syntax for a relative import is |
@StefanKarpinski Does UPDATE: Duh, that's what you propose in #4600. Sorry. |
👍. If we are going to do this, 0.4 would be a good time to do it. |
👍 Please go ahead and clean some of this up (for 0.4!) |
instead of having two import mechanisms to distinguish between extending or not, why not signal extension at the extension site itself via a keyword or annotation at the function definition, e.g. override keyword before function? Simillar to |
This has the advantage that one clearly sees that the function is overriding another (and hence is a method) |
That's already possible, @ssagaert. You do it by explicitly writing the module name in the function definition (e.g., (As an aside, please be careful to enclose macros with backticks `` to prevent pestering other GitHub users). |
👍 to @ssagaert suggestion of using
So pherhaps I think this is more explicit: @extend Base.show(...) = ... Than: import Base: show
# ... several lines here
Base.show(...) = ... |
@Ismael-VC |
@Ismael-VC override word was just a suggestion. It can be extend or anything else meaningful. Also there should be no |
@simonster thank's I didn't know that! @ssagaert so you mean a keyword? I tried something like this but I still suck at macro-foo: module Extend
export @extend
macro extend(x)
mod = x.args[1].args[1].args[1]
met = x.args[1].args[1].args[2]
imp = :(Expr(:import, $mod, $met))
:(Expr(:toplevel, $imp, $(esc(x))))
end
end I know this is not general, still I can't make an expression that returns what parse does: julia> using Extend
julia> type Foo end
julia> @extend Base.show(x::Foo) = Foo
:($(Expr(:toplevel, :($(Expr(:import, Base, :show))), show)))
julia> parse("import Base.show; Base.show(x::Foo) = Foo")
:($(Expr(:toplevel, :($(Expr(:import, :Base, :show))), :(Base.show(x::Foo) = begin # none, line 1:
Foo
end)))) I think that a general and working |
@Ismael-VC I did but I like the 'trick' of @mbauman also. |
Does this being removed from 1.0 mean that we will be left with both How about:
Am I missing some use-case? Maybe this was already suggested... What I like about being explicit about the module when extending is that extension becomes much more local. Right now, when a method is extended, it is common to put the import very close to the top of the module (which might be in a completely different file!). When the extended method is deleted the import statement is usually forgotten. |
I think that's essentially the same as my proposal above, which got a fair amount of support. @JeffBezanson really wants to keep |
I think the difference is in:
Assuming the meaning of "hard binding" is such that you can extend it without module prefix, in my version there are no hard bindings. If you want to extend, you module prefix it exactly where you extend it. No spooky
Isn't forcing module prefix dealing with that? Or are we talking about non modules like:
Both Keeping |
Yes; if you had to qualify functions to extend them then this point would be irrelevant. |
I see it the opposite way; making people switch from |
From reading the thread, it seems the main value in having two keywords is to differentiate between bindings that can be extended or not (hard binding). With that in mind, I think there are two viable solutions:
In either case I suggest
Then |
Current behaviour
Suggestion
The nice things about this is, that importing more corresponds to writing more. I.e. you start with You can also do Compromise for backwards compatibility:
keep around |
@FelixBenning: |
Just to mirror what I've said on slack and so that it doesn't vanish in the slack hole: I don't think making |
Further, |
@tpapp either I have misunderstood the documentation again, or It does not really matter which one of us is right - in either case the current situation is oviously a mess if we can't even figure out what everything does. @mbauman good point - I forgot about that. I don't really care about the But if you do not want that at all, you could of course also go for
or
But whatever the end result is, it should be consistent. And at the moment it just is not. |
Check the following for the semantics of
And this for the semantics of
|
@FelixBenning: yes, I think you misunderstood. FWIW, I think that the "... makes Incidentally, rereading this topic I am wondering if #25306 brought us to a sort of local optimum, and the only decision that remains is whether we need non-extensible imports into the namespace (currently This is how I would approach the status quo in the docs:
The order more or less reflects use cases encountered with more advanced usage. All of the above applies to submodules, with |
What about this:
Or we use |
A very common use (especially in "scripts", but also packages for certain styles is) using Foo, Bar, Baz and just relying on exported symbols. There would be some benefit from keeping this the simplest, possibly as simple as it is now. |
Okay, so can I extend |
Not unless you bring
I am not quite sure about this — however, if you have questions about modules and namespaces, please kindly use the Discourse forum.
Only in the sense that you have to be able to refer to a function somehow using a qualified name before adding methods to it.
I think it is, in a kind of quirky way. In that particular example, if all you do is I do agree that it could be written better, as I said above. A lot of people not used to namespaces find it confusing. And, TBH, the whole |
Okay so here is the thing: It is absolutely not obvious that you can extend every function with the full name if the module is in the namespace. I know that this is current behaviour, but I don't think that anyone who does not know that already would assume that. Especially because being in the namespace does not always mean that it is also extendible. If I do Using this assumption it would make sense, if
So this is what I tried to represent with my table. If two different words are used (import/using) then they should do two different things and that should be clear cut. If A good alternative is to remove import completely as @martinholters suggests. You just simply can not have two words which are just randomly used for certain things. If Just because you can extend everything by its full name right now if the module is in the namespace, does not mean that this is an obvious or straightforward thing. Either being in the namespace is enough, then I should also be able to extend |
I agree, which is why I argue for a rewriting of the docs. However, that is tangential to the current issue. It would be best to keep (1) proposals for improving the documentation on the current API and (2) proposals to redesign it separate, even if the two are somewhat related. I plan to make a PR for (1) soon. |
@tpapp You can not document something which does inherently not make sense. Neither of these documentations is correct:
Any of these would be acceptable. But none of these are actually reality. Reality is currently that there are two different words used for "importing stuff" but they don't actually have a distinct use case. It is like a |
The current modules API is well-defined, so it can be documented (it already is, I just think it should be better).
Please be so kind as to wait for my (or someone else's) PR and comment on the actual text that will be there. Positing hypothetical documentation and then claiming that it is incorrect is just adding noise to this discussion. |
@tpapp maybe I should have said,
I mean in a sense the code is all the documentation you need right? Whats wrong with that? The time it takes to digest it. And I currently see no brief way to describe how it works, because it is riddled with exceptions. Exceptions which should not be there in the first place. Do you really not see what I am trying to convey? |
I think there is general agreement that the current situation is unnecessarily complex and inadequately documented. And no doubt, simplifying the machinery will make documenting it easier. But such simplification will be breaking, so cannot be done before 2.0. So is your point that improvement to the documentation before that wouldn't make sense? Then I disagree. I do see two separate issues: Simplification to be done with 2.0 (which this issue is about) which will (hopefully) include the necessary documentation updates and improving the documentation of the current workings which by reading this thread seems badly required but is another issue. |
After doing #38271, I think that outstanding questions are How to handle adding methods to functions in other modules
Which syntax handles export lists and just the module name
(1|2) & 2 would allow unification into a single keyword, either using LinearAlgebra, Random, StaticArrays I am not sure it is worth it, even without considering the breaking change. This is not one of those problems that offer a clean solution that the original design just missed; there are trade-offs. I would wait and see if better documentation can improve user experience while keeping the current (1.0) setup. |
For 2.0 I think just a clean up of the syntax to be more consistent and descriptive of what is actually happening would be nice. Something like:
|
From the mailing list:
Stefan:
Seems this is still quite a point of confusion for newcomers.
The text was updated successfully, but these errors were encountered: