Pergunta

Vamos dizer que você tem um módulo Fortran 90 contendo muitos de variáveis, funções e sub-rotinas. Em sua declaração USE, que convenções você segue:

  1. explicitamente declarar que variáveis ??/ funções / sub-rotinas que você está usando com a sintaxe , only :, como USE [module_name], only : variable1, variable2, ...?
  2. Insira um USE [module_name] cobertor?

Por um lado, a cláusula only torna o código um pouco mais detalhada. No entanto, o obriga a repetir-se no código e se o seu módulo contém muitos de variáveis ??/ funções / sub-rotinas, as coisas começam a olhar incontrolável.

Aqui está um exemplo:

module constants
  implicit none
  real, parameter :: PI=3.14
  real, parameter :: E=2.71828183
  integer, parameter :: answer=42
  real, parameter :: earthRadiusMeters=6.38e6
end module constants

program test
! Option #1:  blanket "use constants"
!  use constants
! Option #2:  Specify EACH variable you wish to use.
  use constants, only : PI,E,answer,earthRadiusMeters
  implicit none

  write(6,*) "Hello world.  Here are some constants:"
  write(6,*) PI, &
       E, &
       answer, &
       earthRadiusInMeters
end program test

Atualizar Esperemos que alguém diz algo como "Fortran? Apenas recode-lo em C #!" para que eu possa descer votar você.


Atualizar

Gosto de Tim Whitcomb resposta , o que compara USE modulename do Fortran com from modulename import * do Python. Um tópico que tem sido no Stack Overflow antes:

  • 'módulo de importação' ou 'a partir do módulo de importação'

    • Em uma resposta , Mark Roddy mencionado:

      não use 'do módulo de importação *'. Para qualquer grande conjunto razoável de código, se você 'import *' seu provavelmente será cimentando-lo para o módulo, incapaz para ser removido. Isso é porque ele é difícil determinar quais itens usados no código são provenientes de 'módulo', tornando-leste para chegar ao ponto onde você acha que você não usar o importar mais, mas sua extremamente difícil ter certeza.

  • Quais são as boas regras de ouro para python importações?

    • do DBR resposta contém

      não fazer a partir x import * - faz seu código muito difícil de entender, como você não pode ver facilmente onde um método veio (de x import *, a partir de y import *; my_func () - onde é my_func definido?)

Então, eu estou inclinado para um consenso de afirmar explicitamente todos os itens que estou usando em um módulo via

USE modulename, only : var1, var2, ...

E, como Stefano Borini menciona ,

[Se] você tem um módulo tão grande que você se sentir compelido a adicionar apenas, isso significa que seu módulo é muito grande. Dividi-lo.

Foi útil?

Solução

É uma questão de equilíbrio.

Se você usar apenas um material poucos a partir do módulo, faz sentido se você adicionar apenas, para especificar claramente o que você está usando.

Se você usar um monte de coisas a partir do módulo, especificando só será seguido por um monte de coisas, por isso faz menos sentido. Você está basicamente cherry-picking o que você usa, mas o fato verdadeiro é que você é dependente desse módulo como um todo.

No entanto, no final, a melhor filosofia é esta: se você está preocupado com a poluição namespace, e você tem um módulo tão grande que você se sentir compelido a adicionar apenas, isso significa que seu módulo é muito grande. Dividi-lo.

Update: Fortran? apenas recodificar-lo em python;)

Outras dicas

Eu costumava fazer apenas use modulename - então, como minha candidatura cresceu, descobri-lo mais e mais difícil de encontrar a fonte para funções (sem se virar para grep) - alguns dos outros códigos flutuando ao redor do escritório ainda usa um -subroutine-per-file, que tem seu próprio conjunto de problemas, mas torna-se muito mais fácil de usar um editor de texto para percorrer o código e rapidamente rastrear o que você precisa.

Depois de experimentar este, eu me tornei um convertido ao uso de use ... only sempre que possível. Eu também começou a pegar Python, e vê-lo da mesma forma que from modulename import *. Há um monte de coisas grandes que os módulos dão você, mas eu prefiro manter meu espaço global rigidamente controlado.

Não exatamente respondendo à pergunta aqui, apenas jogando em outra solução que eu encontrei útil em algumas circunstâncias, se por qualquer motivo você não quer dividir o seu módulo e começar a ter confrontos namespace. Você pode usar tipos derivados para armazenar vários namespaces em um módulo.

Se houver algum agrupamento lógico das variáveis, você pode criar seu próprio tipo derivado para cada grupo, armazenar uma instância desse tipo no módulo e, em seguida, você pode importar apenas o grupo que acontecer de você precisar.

pequeno exemplo: Nós temos um monte de dados, alguns dos quais é a entrada do usuário e alguns que é o resultado de inicializações diversos

.
module basicdata
   implicit none
   ! First the data types...
   type input_data
      integer :: a, b
   end type input_data
   type init_data
      integer :: b, c
   end type init_data

   ! ... then declare the data
   type(input_data) :: input
   type(init_data) :: init
end module basicdata

Agora, se uma sub-rotina só usa dados de init, você importar apenas isso:

subroutine doesstuff
   use basicdata, only : init
   ...
   q = init%b
end subroutine doesstuff

Este não é definitivamente uma solução universalmente aplicável, você obter algum detalhamento extra a partir da sintaxe tipo derivado e, em seguida, ele irá, naturalmente, apenas ajuda se o seu módulo não é o basicdata tipo acima, mas em vez mais de um allthestuffivebeenmeaningtosortoutvariety. De qualquer forma, eu tive um pouco de sorte na obtenção de código que se encaixa mais fácil para o cérebro desta forma.

A principal vantagem do uso, somente para mim é que ele evita poluir o meu namespace global com coisas eu não preciso.

Acordado com a maioria das respostas dadas anteriormente, use ..., only: ... é o caminho a percorrer, tipos de uso quando faz sentido, aplicar pensamento python, tanto quanto possível. Outra sugestão é usar convenções de nomeação apropriadas em seu módulo importado, juntamente com private declarações / public.

Por exemplo, o netcdf utiliza a biblioteca nf90_<some name>, o que limita a poluição namespace no lado do importador.

use netcdf  ! imported names are prefixed with "nf90_"

nf90_open(...)
nf90_create(...)
nf90_get_var(...)
nf90_close(...)

Da mesma forma, o ncio wrapper para isso utiliza a biblioteca nc_<some name> (nc_read, nc_write ...) .

É importante ressaltar que com tais projetos, onde use: ..., only: ... é feita menos relevante, você controlar melhor o espaço de nomes do módulo importado, definindo atributos private / public apropriados no cabeçalho, para que um rápido olhar para ele vai ser suficiente para que os leitores avaliar qual o nível de "poluição" eles estão enfrentando. Este é basicamente o mesmo que use ..., only: ..., mas no lado módulo importado -., Assim, a ser escrito apenas uma vez, não em cada importação)

Mais uma coisa: na medida em que a orientação a objetos e python estão em causa, a diferença na minha opinião é que fortran realmente não incentivar procedimentos de tipo-bound, em parte porque é um padrão relativamente novo (por exemplo, não é compatível com a número de ferramentas, e menos racional, é apenas incomum) e porque quebra o comportamento útil como cópia livre de processo derivado tipo (type(mytype) :: t1, t2 e t2 = t1). Isso significa que muitas vezes você tem que importar o tipo e todos os candidatos a procedimentos do tipo-bound, em vez de apenas a classe. Este código fortran sozinho marcas mais detalhado em comparação com python e soluções práticas, como uma convenção de nomenclatura prefixo pode vir a calhar.

IMO, a linha de fundo é: escolher o seu estilo de codificação para as pessoas que vai lê-lo (o que inclui a sua auto mais tarde), como ensinado por python. O melhor é o mais detalhado use ..., only: ... em cada importação, mas em alguns casos uma convenção de nomenclatura simples irá fazê-lo (se você for disciplinado o suficiente ...).

Sim, por favor use use module, only: .... Para grandes bases de código com vários programadores, torna o código mais fácil de seguir por todos (ou apenas grep uso).

Por favor, faça uso não incluem, use um módulo menor para que, em vez. Incluir é uma inserção de texto do código fonte que não é verificada pelo compilador, ao mesmo nível que o módulo de uso, consulte: Fortran: Diferença entre INCLUEM e módulos . Include geralmente torna mais difícil para os seres humanos e computador para usar o código que significa que ele não deve ser usado. Ex. de MPI-Fórum: "O uso da mpif.h arquivo de inclusão é fortemente desencorajado e pode ser preterido em uma versão futura do MPI." ( http://mpi-forum.org/docs/mpi -3.1 / mpi31-relatório / node411.htm ).

Eu sei que sou um pouco tarde para a festa, mas se você está apenas depois de um conjunto de constantes e não necessariamente valores computados, você poderia fazer como C e criar um arquivo de inclusão:

dentro de um arquivo, por exemplo, constants.for

real, parameter :: pi = 3.14
real, parameter :: g = 6.67384e-11
...


program main
    use module1, only : func1, subroutine1, func2 
    implicit none

    include 'constants.for'
    ...
end program main

Editado para remover "real (4)", como alguns pensam que é uma prática ruim.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top