j3-fortran / fortran_proposals

Proposals for the Fortran Standard Committee
178 stars 15 forks source link

Namespace for modules #1

Open certik opened 4 years ago

certik commented 4 years ago

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.

aradi commented 2 years ago

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 commented 2 years ago

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

ivan-pi commented 2 years ago

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.