Skip to content

Namespace for modules #1

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

Open
certik opened this issue Oct 16, 2019 · 115 comments
Open

Namespace for modules #1

certik opened this issue Oct 16, 2019 · 115 comments
Labels
Clause 14 Standard Clause 14: Program units Fortran 202y Proposals targeting the standard after F2023 under consideration Has been submitted to the committee

Comments

@certik
Copy link
Member

certik commented Oct 16, 2019

So you can require module data to be referenced like module.var:

use, namespace :: utils
...
call utils%savetxt()

One issue with just use utils is that it still pollutes your local namespace with savetxt, so that's the reason for use, namespace :: utils.

Other alternatives for syntax: use utils, only (or perhaps use utils, only:). Another alternative is use namespace utils (suggested by Milan Curcic). Or perhaps use, namespace :: utils, to by compatible with the existing syntax like use, intrinsic :: iso_fortran_env.

Initially proposed by Michael Zingale and further discussed at Twitter.

@zjibben zjibben added the unsubmitted Has not been submitted to the committee yet label Oct 16, 2019
@certik
Copy link
Member Author

certik commented Oct 16, 2019

The paper is submitted at https://j3-fortran.org/doc/year/19/19-246.txt. I will try to get feedback on it from the committee. CC @zingale.

@certik certik added under consideration Has been submitted to the committee Fortran 202y Proposals targeting the standard after F2023 and removed unsubmitted Has not been submitted to the committee yet labels Oct 16, 2019
@cmacmackin
Copy link

Agree, this seems like a good feature.

@certik
Copy link
Member Author

certik commented Oct 21, 2019

So the committee unfortunately did not consider this proposal at the meeting last week. I was hoping to get at least a general "yes" or "no" direction from the committee. But I talked to a few members directly, and I did not hear any "this is a bad idea", or "this should not be done".

Here is my plan:

  1. Write a high quality full proposal for this. This means more use cases, we have to brainstorm any possible issues, and some members of the committee like to structure any new features as "requirements", "specification" and "syntax", so we should incorporate all that.

  2. I will ask on the j3 mailinglist once a more complete proposal is ready to get some feedback

  3. I will ensure that this gets to the committee program for next meeting to be officially considered for the 202y standard.

@certik
Copy link
Member Author

certik commented Oct 23, 2019

@septcolor that's a valid concern. My plan to overcome this is to use this github repository to get support for proposals. If the Fortran community puts thumbs up for a proposal, or otherwise expresses strong interest, then relatively to other ideas proposed here it will be obvious which proposals are high priority, and which are low priority. And then it will be easier to argue for a particular proposal at the committee.

@FortranFan
Copy link
Member

FortranFan commented Nov 3, 2019

Fyi a new thread at comp.lang.fortran inquiring of a missing feature in current Fortran which can be met by the proposal here:
https://groups.google.com/d/msg/comp.lang.fortran/nYdFG0PCTWo/rjjLlAteDgAJ

By the way, I had a similar interest along the lines of this proposal several years ago:
https://groups.google.com/forum/#!msg/comp.lang.fortran/sNNnQaoqC9I/JFAEgsbeAPMJ

@certik
Copy link
Member Author

certik commented Nov 3, 2019

Thanks @FortranFan. This is one of the popular issues in here and I am going to insist for the committee to consider it at the next meeting. However, I welcome any help with improving the current proposal (linked above).

@FortranFan
Copy link
Member

@certik wrote:

..However, I welcome any help with improving the current proposal (linked above).

@certik and others interested in this, if you haven't already please take a note of comments online, especially by Ian Harvey at comp.lang.fortran such as this one:

Look at the last 3 questions in that comment: addressing these questions suitably will strengthen the proposal. Some aspects that come to my mind with these questions include:

  1. USE statements can include unnamed operators (+,-*,/, etc.), assignment(=), etc. What is the impact of this proposal on their semantics?
  2. What about named entities which are operators in USE statements e.g., operator(.cross_product.)? Does x .cross_product. y become x foo::operator(.cross_product.) y a la C++?
  3. What about generic interfaces and their extension via USE statements?
  4. Current standard has scoping unit semantics with MODULE subroutines/functions (e.g., for use in SUBMODULEs), INTERFACEs. BLOCK constructs, etc. that can be impacted by USE statements. What happens with them?

@certik
Copy link
Member Author

certik commented Nov 6, 2019

@FortranFan thanks a lot for pointing these potential issues out. Let's address them.

This was referenced Nov 14, 2019
@gronki
Copy link

gronki commented Nov 19, 2019 via email

@qolin1
Copy link

qolin1 commented Dec 21, 2019

Gets my vote FWIW. I have wanted this for some time, without knowing its name was "namespaces".

@certik
Copy link
Member Author

certik commented Dec 22, 2019

@qolin1 I just called it "namespaces" for a lack of a better name. We will keep pushing for this at our next committee meeting. I think this is a popular feature.

@gronki
Copy link

gronki commented Dec 23, 2019 via email

@certik
Copy link
Member Author

certik commented Dec 23, 2019

@klausler, @gronki make sure you put thumbs up on issues that you find high priority, and let's collaborate on the top priority issues. I just created #122 for that purpose, let's discuss the list of top priority issues there.

Regarding this issue #1, for me personally this is a huge quality of life improvement, that is a relatively simple feature, and yet it allows to use Fortran modules more like Python. How this stacks up against some other features that we want to push in terms of prioity, that's for a discussion to be had at #122.

@jme52
Copy link

jme52 commented Jan 16, 2020

  1. I think this is a good idea.
    I worked for many years in a code where policy was that module procedures needed to start with the name or the acronym of the module. This would make that code neater.

  2. I like the use, namespace :: utils syntax. I think namespace should be optional and disabled by default for backwards compatibility (sorry if I am stating the obvious).

  3. I agree that % is the fortranic syntax. However, its use may increase the complexity of the rules about scope of identifiers, which will need to be significantly rewritten.

  4. Would it be possible to simultaneously add the possibility of renaming modules (namespaces) as part of the use declaration?

    use, non_intrinsic, namespace :: eh => electronic_history
    implicit none
    call eh%initialise_method

@everythingfunctional
Copy link
Member

I like the idea of namespaces, and I like @jme52 syntax example, use, namespace :: sm => some_module, but one thing that should be pointed out is that you would not then be able to do use, namespace :: sm => some_module, only: thing1, thing2. Or at least I don't think you should be able to. Just thought this should be made explicit.

@jme52 , Why do you think using % increases the complexity of rules about scope? Do you have an example of that?

@milancurcic
Copy link
Member

some users will want the processor to enforce the use of the module name as a qualifier which in turn requires the use of a different syntax to let the processor know that that is a requirement.

Indeed, once you can namespace, simple and common names will proliferate in modules and the user should have a way to not have them pollute the global namespace.

@certik
Copy link
Member Author

certik commented Oct 1, 2020

@klausler That seems to be a very similar idea to what I proposed above #1 (comment), but I thought you didn't like it. Are you proposing exactly the table in that comment, or are you proposing the following table (in other words, do you want to allow use A, only: or not):

Case Python Julia Chapel Fortran
1. import A import A use A only use A
2. import A as B import A as B use A as B only use B => A
3. from A import x using A: x use A only x use A, only: x
4. from A import x as y import A: x as y use A only x as y use A, only: y => x
5. from A import * using A use A use A

Furthermore, in all cases 1.-5., the module name A (or B in 2.) will always be created as a namespace, in addition to importing all the symbols from it in 1., 2. and 5. (and only x or y in 3. and 4.).

If the above is what you are proposing, I can see all kinds of extensions in the compiler, for example with an option the compiler can start warning (by supplying -Wimplicit-use) if you do use A but use any implicitly imported symbol from the module (in case 1.), and if you want to use case 5. and not get a warning, you can do use A, only: *. The syntax would be natural, and I would enable that -Wimplicit-use warning option for my codes (I currently never use use A anyway). In this case, it would make sense to consider adding the syntax use A, only: * into this proposal also, to make it standardized: in other words, use A, only: * would be equivalent to use A, but the compiler would only warn if you use some symbol implicitly in the latter case. That should be strictly backwards compatible, and yet doing exactly what I would like. People who don't like this (or for older codes) would just not enable the -Wimplicit-use compiler warning.

@certik
Copy link
Member Author

certik commented Oct 1, 2020

Ok, so to summarize, you are proposing this:

Case Python Julia Chapel Fortran
1. import A import A use A only use A, only:
2. import A as B import A as B use A as B only use B => A, only:
3. from A import x using A: x use A only x use A, only: x
4. from A import x as y import A: x as y use A only x as y use A, only: y => x
5. from A import * using A use A use A

Where the cases 1. and 2. are exactly equivalent to Python, but cases 3., 4. and 5. are a "superset" of Python: they import the x, y or all symbols as in Python respectively, but also in addition make the module name A available as a namespace in Fortran (which does not happen in Python).

I like this proposal.

@certik
Copy link
Member Author

certik commented Oct 1, 2020

Thanks Peter. My goal is to get it pre-approved by the committee, saying "yes, we want this feature, as long as all the issues can be satisfactorily resolved". The minute it does, I am sure multiple people from the community will help. Obviously nobody wants to put in weeks of work if the committee decides they don't want this feature in the first place.

I plan to prototype this in a compiler.

@FortranFan
Copy link
Member

FortranFan commented Oct 1, 2020

@klausler wrote Oct. 1, 2020 6:48 PM EDT:

The harder part of this proposal remains to be discussed, too. ..

I agree.

As I alluded to earlier, Fortran language can do better by gaining the formal concept of namespaces. Ideally, features such as this are best handled as part of that effort.

Considering the complexities and constraints involved with piecemeal attempts, a prototype implementation for the formal namespace concept itself will be nice. The aspects such as this thread can be subparts of such an initiative.

@certik
Copy link
Member Author

certik commented Oct 2, 2020

I personally feel we don't need namespaces, but I agree with Vipul that we should keep it in mind and not close doors by introducing something that would make it very hard to introduce namespaces later if the community wishes that.

Modules and a well designed "import" is what I personally would like to see. Fortran is very close.

@septcolor regarding who can contribute: I strongly encourage you and anyone else to contribute. The committee and the community is composed of both users and compiler vendors / experts, and we need both to collaborate on new features. Leaving things just to compiler vendors, or just to users to design is not optimal, we need a healthy collaboration of both groups.

@FortranFan
Copy link
Member

@wclodius2 wrote Oct. 1, 2020

There seems to have been a consensus that there should be a poll/vote on the preferred syntax. As there has been a significant pause in postings on this issue, I think it is an appropriate to summarize our current syntactic options to prompt more suggestions for options. There are four orthogonal choices in the syntax:

What word to use as the keyword
..

If there are folks who aren't enthused by any of the keywords thus far, here's another one that can perhaps considered for the poll? PREFIX:

use, prefix(ut) :: utils, only : savetxt
..
call utXsavetxt(..)

@milancurcic milancurcic added the Clause 14 Standard Clause 14: Program units label Oct 27, 2021
@aradi
Copy link
Contributor

aradi commented May 9, 2022

I think, the idea with prefix is a really nice one. But, maybe prefixed (as adjective) is more aligned with what we have already, e.g.

use, intrinsic, prefixed :: iso_fortran_env        ! if entire module name is used as prefix
use, intrinsic, prefixed(ife) :: iso_fortran_env  ! if specified prefix is used

@certik certik mentioned this issue May 13, 2022
@beddalumia
Copy link

beddalumia commented Sep 17, 2022

  • use stdlib_stats, as: stats
  • use stdlib_stats, as is

I would find it rather confusing, not the first one, which I think is neat, but the second: "as is" makes me think about "as given" / "raw" / "as provided", so equivalent to the current behavior withuse stdlib_stats (which I hope you want to preserve: there are cases where one wants a namespace, there are cases where it just adds unnecessary verbosity, that's why python offers also the from x import z syntax).

What about

  • use stdlib_stats, as namespace: stats
  • use stdlib_stats, as namespace

instead?

I find it very "natural-english-alike", which is imo what Fortran has always striven for...

@shahmoradi
Copy link

How about

use, intrinsic, namespace :: iso_fortran_env        ! if the entire module name is used as a prefix
use, intrinsic, namespace :: ife => iso_fortran_env  ! if the specified prefix is used

@aradi
Copy link
Contributor

aradi commented Sep 18, 2022

use, intrinsic, namespace :: ife => iso_fortran_env ! if the specified prefix is used

I think, that would be quite Fortranic and nice, I like it a lot! Only, I'd rather go with an adjecive (prefixed or namespaced) here, as it reads very nicely: "Use the intrinsinc, prefixed module iso_fortran_env"

@beddalumia
Copy link

beddalumia commented Sep 18, 2022

Maybe prefixed, namespaced does not look that much like english :)

@ivan-pi
Copy link

ivan-pi commented Sep 24, 2022

Does this usage case help motivate the namespace proposal?

I have a clash between a dummy argument name and a typename.

module object_module
type :: object
end type
contains
subroutine handle_object(object)
class(*), intent(in) :: object
select type(object)  ! the variable
   type is (object)  ! the typename
      ! do something
end select
end subroutine
end module

To resolve the name clash, I have the following options

  1. Pick a different name for the object dummy argument. Since Fortran dummy argument names are part of the public interface, this may not be desirable as it could break existing code.
  2. Pick a different name for the derived-type. Also not desirable as it could break existing code.
  3. Place the implementation into a submodule, and re-import the type from a separate module, renaming it in the process, e.g.:
module object_m
implicit none

type :: object
end type

interface 
module subroutine handle_object(object)
class(*), intent(in) :: object
end subroutine
end interface

end module

module rename_object
use object_m, only: object_m_object => object
public
end module

submodule (object_m) object_impl
contains
   module subroutine handle_object(object)
      use rename_object
      class(*), intent(in) :: object
      select type(object)
         type is (integer)
            print *, object
         type is (object_m_object)
            ! ...
      end select
   end subroutine
end submodule

Solution 3 is not very desirable because I suddenly have a new module, just to rename a type. It would be much nicer to just to object_m % object or (object_m) object (copying the (module) submodule syntax) and refer directly to the entity in the parent module.

certik pushed a commit that referenced this issue Jun 30, 2024
Update cmplx-real-pointers.txt
@certik
Copy link
Member Author

certik commented Apr 2, 2025

This was put on the feature list for F202Y.

But then it was dropped in https://j3-fortran.org/doc/year/25/25-119r1.txt.

@everythingfunctional
Copy link
Member

This was put on the feature list for F202Y.

But then it was dropped in https://j3-fortran.org/doc/year/25/25-119r1.txt.

It was not necessarily dropped, but the initial plan for an implementation was decided to not be ideal. During the discussion it was suggested that maybe a new construct would be a way to go. Something like

namespace a
  use b, only: c
end namespace
...
a%c = ...

A namespace would then be a first class entity.

So we don't know what the feature will look like yet, but it wasn't dropped from the work list (WG5 has to do that).

@certik
Copy link
Member Author

certik commented Apr 2, 2025

Thanks @everythingfunctional for the feedback. The main objection seems to be:

Furthermore, module names are not passed through subsequent use or host
association, which means it would only work in a scope that directly uses
the module. That would make the feature useless. Passing module names
through use or host association, as class one identifiers (which they are),
cannot be changed without introducing an incompatibility.

Do you understand what exactly the issue is here? Yes, one “passes” implicitly the module name into nested scopes, just like in Python. What exactly is the incompatibility? If you declare a local variable of the same name as the module, it will shadow it.

(I also asked here: https://fortran-lang.discourse.group/t/why-do-we-need-typeof/9454/56.)

@everythingfunctional
Copy link
Member

everythingfunctional commented Apr 2, 2025

Yes, one “passes” implicitly the module name into nested scopes

Except that currently transitive module names are not implicitly brought into scope by a use statement. Making that happen would not be backwards compatible, because you can't have things with the same name defined in the same scope. I.e. the following example is currently valid, but would become invalid.

module a
end module
module b
  use module a
end module
use module b
integer a
end

@certik
Copy link
Member Author

certik commented Apr 2, 2025

@everythingfunctional good example. So the issue is with transitive modules? I would keep the above example valid and behaving just like today (i.e. use b will not bring a into the scope), but the following example would also work:

module a
integer :: something
end module

module b
use module a
end module

use, namespace :: b
print *, b%a%something
end

Can you see any problem with that?

P.S. your example does not actually compile with GFortran:

module amod
end module

module b
use amod
end module

program main
use b
integer amod
end

It gives:

a.f90:10:12:

   10 | integer amod
      |            1
Error: Symbol ‘main’ at (1) cannot have a type

So if this is valid, it is not used by people much, if it doesn't even compile.

@everythingfunctional
Copy link
Member

That seems potentially workable, if possibly tricky to define in the standard, but I haven't thought about it real hard yet, and you'll have to convince Data subgroup to revisit it. From your example though, wouldn't b%something be more appropriate?

I'm surprised that example produces an error, and the message doesn't look right. I'm sure you're right that people rarely use the name of a module for something else, but it's still generally better to have backwards compatibility when possible.

@certik
Copy link
Member Author

certik commented Apr 2, 2025

From your example though, wouldn't b%something be more appropriate?

Good point, I meant to write it like this:

module a
integer :: something
end module

module b
use, namespace :: a
end module

use, namespace :: b
print *, b%a%something
end

Btw, the syntax you used use module a, is that meant as the equivalent of mine use, namespace :: a? Yours is easier to type.

@everythingfunctional
Copy link
Member

Btw, the syntax you used use module a, is that meant as the equivalent of mine use, namespace :: a?

Was just typing without thinking hard about syntax and somehow got an extra word. It was unintentional.

@klausler
Copy link

klausler commented Apr 2, 2025

You can avoid this confusion by omitting the use statements entirely. Instead, use some syntax to distinguish a module name in a qualified identifier, e.g., %a%something. The semantics would be simple -- it's equivalent to having use a, only: DISTINCTNAME => something in scope.

@jacobwilliams
Copy link

I was wondering if any thought has been given to namespaces enabling using libraries in the same project that have the same module names? Currently, I think it's not possible with Fortran? e.g., you have two separate libraries used internally by two separate libraries, but both named kinds or something generic like that. Currently, we have to prepend hopefully unique names to modules like this to avoid this. But, maybe something like namespaces would be a better solution here?

@certik
Copy link
Member Author

certik commented Apr 2, 2025

@jacobwilliams I think that's a separate feature: nesting modules like in Python, which allows you to have the same module name at different places in the (directory) tree of modules.

@everythingfunctional
Copy link
Member

any thought has been given to namespaces enabling using libraries in the same project that have the same module names?

Not really. And even if we did do something to help with that problem, it certainly wouldn't be in a way that doesn't require you to change the module, at which point just renaming the module isn't really that bad.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Clause 14 Standard Clause 14: Program units Fortran 202y Proposals targeting the standard after F2023 under consideration Has been submitted to the committee
Projects
None yet
Development

No branches or pull requests