2009-08-06 17 views
32

Digamos que tiene un módulo Fortran 90 que contiene lotes de variables, funciones y subrutinas. En su estado de cuenta USE, que la convención usted sigue:¿Cómo se utilizan datos del módulo Fortran 90?

  1. explícitamente declarar las variables que/funciones/subrutinas que está utilizando con la sintaxis , only :, como USE [module_name], only : variable1, variable2, ...?
  2. Insertar una manta USE [module_name]?

Por un lado, la cláusula only hace que el código sea un poco más detallado. Sin embargo, te obliga a repetirte en el código y si tu módulo contiene lotes de variables/funciones/subrutinas, las cosas comienzan a parecer ingobernables.

He aquí un ejemplo:

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 

actualización Esperemos que alguien dice algo así como "Fortran Sólo recodificar en C#?!" así puedo votar por ti.


actualización

me gusta Tim Whitcomb's answer, que se compara de Fortran USE modulename con Python de from modulename import *. Un tema que ha estado en desbordamiento de pila antes:

  • ‘import module’ or ‘from module import’

    • In an answer, Mark Roddy mencionó:

      no usan 'del módulo de importación *'. Para cualquier conjunto grande razonable de código, si 'importa *' es probable que sea que lo cementa en el módulo, no se puede eliminar . Esto se debe a que es difícil determinar qué elementos utilizados en el código vienen de 'módulo', por lo que es al este para llegar al punto de donde cree que no utiliza la importación más, pero su extremadamente difícil para estar seguro.

  • What are good rules of thumb for python imports?

    • dbr's answer contiene

      no lo haga desde x importación * - que hace su código muy difícil de entender, ya que no se puede ver fácilmente dónde un método provino de (de x import *; from y import *; my_func() - where is my_func definido?)

lo tanto, me estoy inclinando hacia un consenso de establecer explícitamente todos los artículos que estoy usando en un módulo a través

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

Y como Stefano Borini mentions,

[si] tiene un módulo tan grande que se siente obligado a agregar SOLAMENTE, significa que su módulo es demasiado grande. Dividirlo.

+3

Uno de los problemas con Fortran es que cuando importas desde módulos siempre lanzarás todo en el espacio de nombres global, como en Javascript. En python, puedes hacerlo desde foo.bar import *, pero también desde foo import bar. En Fortran, no tienes elección. Cada vez que usa USE, realiza una importación * e incluye todo en el espacio de nombres global. Este es uno de los peores problemas de Fortran 9X. –

+0

@StefanoBorini: ¿esa última frase implica que el problema se resuelve en versiones fortran más recientes? – naught101

+0

@ naught101 nope –

Respuesta

15

Es una cuestión de equilibrio.

Si usa solo algunas cosas del módulo, tiene sentido si solo lo agrega, para especificar claramente qué está usando.

Si usa muchas cosas del módulo, especificar SÓLO irá seguido de muchas cosas, por lo que tiene menos sentido. Básicamente, estás eligiendo lo que usas, pero la verdad es que dependes de ese módulo como un todo.

Sin embargo, al final la mejor filosofía es esta: si le preocupa la contaminación del espacio de nombres, y tiene un módulo tan grande que se siente obligado a agregar ÚNICAMENTE, significa que su módulo es demasiado grande. Dividirlo.

Actualización: Fortran? solo recodifíquelo en python;)

+5

Esta es una heurística útil para "¿cuán grande debe ser mi módulo?". –

3

La principal ventaja de USE, SÓLO para mí es que evita contaminar mi espacio de nombres global con cosas que no necesito.

23

Solía ​​hacer use modulename - entonces, a medida que mi aplicación creció, me resultó cada vez más difícil encontrar la fuente para las funciones (sin recurrir a grep) - algunos de los otros códigos flotando por la oficina todavía usa una subrutina por archivo, que tiene su propio conjunto de problemas, pero hace que sea mucho más fácil usar un editor de texto para moverse a través del código y rastrear rápidamente lo que necesita.

Después de experimentar esto, me he convertido en un convertido para usar use ... only siempre que sea posible. También comencé a buscar Python, y lo veo de la misma manera que from modulename import *. Hay muchas cosas geniales que los módulos le brindan, pero prefiero mantener mi espacio de nombres global estrictamente controlado.

+0

Me gusta su analogía para importar módulos Python - ¡buen pensamiento! – Pete

+1

Exactamente. Solo uso la importación explícita "usar ... solo" como en Python. Solo uso "de ... importación". Creo que este es el enfoque correcto. –

5

No estoy respondiendo exactamente la pregunta aquí, simplemente lanzando otra solución que he encontrado útil en algunas circunstancias, si por alguna razón no desea dividir su módulo y comenzar a tener conflictos de espacio de nombres. Puede usar tipos derivados para almacenar varios espacios de nombres en un módulo.

Si hay alguna agrupación lógica de las variables, puede crear su propio tipo derivado para cada grupo, almacenar una instancia de este tipo en el módulo y luego puede importar solo el grupo que necesite.

Pequeño ejemplo: Tenemos una gran cantidad de datos, algunos de los cuales son de entrada del usuario y otros son el resultado de varias inicializaciones.

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 

Ahora bien, si una subrutina sólo utiliza datos de init, se importa más que eso:

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

Esto definitivamente no es una solución de aplicación universal, se obtiene algún nivel de detalle adicional de la sintaxis tipo derivado y luego por supuesto, apenas ayudará si su módulo no es del tipo basicdata anterior, sino más bien de una variedad allthestuffivebeenmeaningtosortout. De todos modos, he tenido un poco de suerte para obtener un código que se adapte mejor al cerebro de esta manera.

0

Yo sé que soy un poco tarde a la fiesta, pero si estás sólo después de un conjunto de constantes y no necesariamente los valores calculados, se puede hacer como C y crear un archivo de inclusión:

dentro de una archivo, por ejemplo, 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 eliminar "real (4)", como algunos piensan que es una mala práctica.

+0

Por favor, no enseñe a la gente el mal hábito de usar 'real (4)' cuando la pregunta original no lo requiera. Además, no puedo aceptar que el enfoque de inclusión sea mejor o incluso más simple. –

+0

real (4) es copiar/pegar y la fuerza del hábito en mi extremo. Pensé en tu otro comentario pero de todos modos lo dejé. Hay miles de formas en que las personas pueden lograr lo mismo. Es importante que las personas experimenten y encuentren lo que les gusta. En mi opinión, el archivo "incluir" solo sería más difícil si no estuviera usando un archivo MAKE y no agregó el "-I". – Forrest

1

De acuerdo con la mayoría de las respuestas dadas previamente, use ..., only: ... es el camino a seguir, utilice tipos cuando tenga sentido, aplique python thinking tanto como sea posible. Otra sugerencia es utilizar las convenciones de nomenclatura apropiadas en su módulo importado, junto con las declaraciones private/public.

Por ejemplo, la biblioteca netcdf utiliza nf90_<some name>, lo que limita la contaminación del espacio de nombres en el lado del importador.

use netcdf ! imported names are prefixed with "nf90_" 

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

Del mismo modo, el envoltorio ncio a esta biblioteca utiliza nc_<some name> (nc_read, nc_write ...).

Es importante destacar que con este tipo de diseños en los que use: ..., only: ... se hace menos relevante, que le controlar mejor el espacio de nombres del módulo importado mediante el establecimiento de private/public atributos adecuados en la cabecera, de modo que un rápido vistazo será suficiente para que los lectores para evaluar a qué nivel de "contaminación" se enfrentan. Esto es básicamente lo mismo que use ..., only: ..., pero en el lado del módulo importado; por lo tanto, debe escribirse una sola vez, no en cada importación.

Una cosa más: en lo que respecta a orientación de objeto y python, una diferencia en mi opinión es que fortran realmente no fomenta procedimientos de tipo ligado, en parte porque es un estándar relativamente nuevo (por ejemplo, no compatible con una cantidad de herramientas, y de manera menos racional, es inusual) y porque rompe el comportamiento práctico, como la copia de tipo derivada sin procedimientos (type(mytype) :: t1, t2 y t2 = t1). Eso significa que a menudo tiene que importar el tipo y todos los posibles procedimientos de escritura de tipo, en lugar de solo la clase. Esto solo hace que el código fortran sea más detallado en comparación con Python, y las soluciones prácticas como una convención de nomenclatura de prefijo pueden ser útiles.

IMO, la conclusión es: elija su estilo de codificación para las personas que lo leerán (esto incluye su autorretrato posterior), como lo enseña python. Lo mejor es el use ..., only: ... más detallado en cada importación, pero en algunos casos una simple convención de nomenclatura lo hará (si eres lo suficientemente disciplinado ...).

1

Sí, utilice use module, only: .... Para grandes bases de código con múltiples programadores, hace que el código sea más fácil de seguir por todos (o simplemente use grep).

No utilice include, use un módulo más pequeño para eso. Incluir es una inserción de texto del código fuente que el compilador no verifica en el mismo nivel que el módulo de uso, ver: FORTRAN: Difference between INCLUDE and modules. Include generalmente hace que sea más difícil para los humanos y la computadora usar el código, lo que significa que no se debe usar. Ex. from mpi-forum: "El uso del archivo de inclusión mpif.h está muy desaconsejado y puede ser desaprobado en una versión futura de MPI". (http://mpi-forum.org/docs/mpi-3.1/mpi31-report/node411.htm).

+0

No agregue las oraciones como la primera en su segundo párrafo. O bien su respuesta es adecuada como respuesta independiente o no lo es y luego no la publique. Obtenga el representante primero para publicar los comentarios, es fácil. Con oraciones como esa, solo invita a las personas a votar para que su pregunta sea eliminada. Hay una razón de eliminación especial para tales respuestas/comentarios. –

+0

@VladimirF y esa es una buena idea y una razón válida para eliminar. Me encontré con esto por casualidad y suponiendo que olvidaría que decidí publicar porque creo que el uso de la inclusión es una mala práctica que debe ser desaprobada, al menos activamente desaconsejada. Generalmente lo hace más difícil tanto para los humanos como para la computadora y luego no debería usarse. Ex de mpi-forum: "El uso del archivo de inclusión mpif.h se desaconseja enérgicamente y puede quedar obsoleto en una versión futura de MPI". (https://www.mpi-forum.org/docs/mpi-3.1/mpi31-report/node411.htm). Entonces di una respuesta válida y agregué un comentario. Publicación editada. –

+0

Estoy de acuerdo. Puedes poner esta cita en la respuesta. Desafortunadamente, el manual de OpenMPI todavía muestra solo 'include mpif.h' antes de cada entrada manual de subrutina, al menos en la versión 1.8. –

Cuestiones relacionadas