Skip to content
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

Only make exported bindings available with import #12069

Open
mauro3 opened this issue Jul 8, 2015 · 12 comments
Open

Only make exported bindings available with import #12069

mauro3 opened this issue Jul 8, 2015 · 12 comments
Labels
kind:breaking This change will break code kind:speculative Whether the change will be implemented is speculative modules

Comments

@mauro3
Copy link
Contributor

mauro3 commented Jul 8, 2015

My (maybe wrong) understanding is that the public API of a package is what its main module exports.

However, exports only impact when using a Package and not when importing. However, for larger scale software projects it is probably often preferable to use import to get the safety benefits of separate name-spaces. But this means that when I program in the "safer" import-mode there is no easy way to tell whether I use the public API or some private feature. So, it's not really safer at all.

I wonder whether it would make sense and be more consistent with using that import only allows access to the exported bindings, and that importall imports all the bindings (and also allows method extension, i.e. as it is now):

module A
export a
a() = 1
b() = 2
end
# Defining a module in-line does an implicit
#import A

# now only exported symbols are available
A.a() # works
A.b() # ERROR: UndefVarError: A.b not defined

importall A
A.b() # now works
A.a(x) = 5 # can now be extended
A.b(x) = 5 # can also be extended

(this needs more working out though)

This would be a breaking change but could maybe be done through depreciation warnings. Worth the hassle though?

Or could/should one write a @safeimport macro doing above?

Related: #8000.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Jul 8, 2015

there seems to be a mixing of terms here. importall is explicitly doing the import of absolutely everything. it's target usage is really interactive development, where you don't really care about safety or conventions, but just want to try out an idea quickly. using makes the exports available. import is the safe option for listing exactly what you want.

@mauro3
Copy link
Contributor Author

mauro3 commented Jul 8, 2015

No, I'm arguing that there should be a construct which only makes the exported variables available through the fully qualified dot-syntax. Reiterating above example, package A defined like so:

module A
export a
a() = 1
b() = 2
end

now using this with, let's call it import_only_exported for the sake of clarity:

import_only_exported A

# now only exported symbols are available with fully qualified syntax
A.a() # works
A.b() # ERROR: UndefVarError: A.b not defined

# none are introduced to the current workspace:
a() # ERROR: UndefVarError: a not defined
b() # ERROR: UndefVarError: b not defined

But it was maybe a bit confusing as I suggested both import and importall be modified slightly (in an effort to keep the number of keywords constant...).

The idea would be that import_only_exported would allow to easily program with only the public API (i.e. what's exported) without having to pollute your name-space with using. I don't think that is possible at the moment but it may be of value?

@nalimilan
Copy link
Member

If field overloading was allowed and .. became the operator for direct field access (#1974), then I'd be in favor of making unexported functions available only using A..b().

But adding yet another variant of import would only create more confusion IMHO.

@toivoh
Copy link
Contributor

toivoh commented Jul 9, 2015

The problem exists also when you are doing specific imports, eg

import A.b

works even though b is not exported in A.

I agree that it should be possible to import things in a way that protects you from importing an unexported symbol by mistake, also when using the more disciplined alternatives to using. This is no simple fix though, and I'm not sure what could be a good solution.

@toivoh
Copy link
Contributor

toivoh commented Jul 9, 2015

Restricting access to A.b seems to require some kind of access restriction as discussed in #12064, but coming up with a form of import that disallows to import A.b seems more about coming up with the right syntax (which is hard enough, of course :)

@mauro3
Copy link
Contributor Author

mauro3 commented Jul 9, 2015

I like @nalimilan's suggestion, if the .. comes along.

@tknopp
Copy link
Contributor

tknopp commented Jul 9, 2015

Would it be possible to chain the private symbols. I.e. that in the initial example b would only be accessible by A.A.b() ? I know that this might currently be a technical problem (since A == A.A) but conceptually this could work

@ScottPJones
Copy link
Contributor

As an alternative to .., which other people have expressed a desire to use for intervals, IIRC, what about .!. I think it is less accident prone (one vs two dots is harder to see), and more visible (exclamation points do grab your attention).?

@DemiMarie
Copy link

I definitely want a way to be able to access the exported members – and only the exported members – using the module name as a namespace qualifier. This is to avoid PHP's massive global namespace, which leads to confusion as to what name comes from what module.

@DemiMarie
Copy link

Ping?

This seems like a major problem for large-scale projects. Common Lisp solved it by separating a:b (accesses only exported symbols in package a) and a::b (accesses any symbol in package a).

@adamryczkowski
Copy link

Can I ask what is the status of this proposal?
Is it placed in the roadmap (and in what shape?), rejected or still under discussion?

@taqtiqa-mark
Copy link

In case it helps.... the following Discourse comment provides and example of how to create private properties for a type.

@brenhinkeller brenhinkeller added the kind:breaking This change will break code label Nov 19, 2022
@brenhinkeller brenhinkeller added the kind:speculative Whether the change will be implemented is speculative label Aug 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:breaking This change will break code kind:speculative Whether the change will be implemented is speculative modules
Projects
None yet
Development

No branches or pull requests