Esta es la respuesta más válida que te podemos dar, sin embargo obsérvala detenidamente y valora si se adapta a tu trabajo.
Solución:
Los módulos son siempre lo correcto para usar 😉
Si tiene un programa F90 muy simple, puede incluir funciones y subrutinas en el bloque ‘contiene’:
program simple
implicit none
integer :: x, y
x = ...
y = myfunc(x)
contains
function myfunc(x) result(y)
implicit none
integer, intent(in) :: x
integer :: y
...
end function myfunc
end program
Entonces, la interfaz de las funciones/subrutinas se conocerá en el programa y no será necesario definirla en un bloque de interfaz.
Para programas más complejos, debe mantener todas las funciones/subrutinas en módulos y cargarlas cuando sea necesario. Por lo tanto, tampoco necesita definir interfaces:
module mymod
implicit none
private
public :: myfunc
contains
function myfunc(x) result(y)
implicit none
integer, intent(in) :: x
integer :: y
...
end function myfunc
end module mymod
program advanced
use mymod, only: myfunc
implicit none
integer :: x, y
x = ...
y = myfunc(x)
end program advanced
El módulo y el programa pueden (en realidad deberían) estar en archivos separados, pero el módulo debe compilarse antes que el programa real.
Secundando y ampliando lo ya dicho. Es mejor poner sus procedimientos (subrutinas y funciones) en módulos y “usarlos” porque con ellos obtiene una verificación automática de consistencia de las interfaces con poco esfuerzo. Las otras formas tienen inconvenientes. Si define la interfaz con un bloque de interfaz, entonces tiene que mantener tres cosas en lugar de dos: la interfaz, el procedimiento en sí y la llamada. Si realiza un cambio, entonces los tres deben modificarse para que sean consistentes. Si usa un módulo, solo se deben cambiar dos. Una razón para usar un bloque de interfaz es si no tiene acceso al código fuente (p. ej., una biblioteca precompilada) o si el código fuente está en otro idioma (p. ej., está utilizando código C a través de ISO C Binding).
El inconveniente del enfoque “contiene” es que los procedimientos contenidos heredan todas las variables locales del programa principal… lo cual no es muy modular y puede ser muy confuso si olvida esta “característica”.
las respuestas de alexurba y MSB son correctas y útiles como siempre; permítanme desarrollar un poco más de detalle en un punto: si los módulos son el camino a seguir (y lo son), ¿para qué sirven las interfaces?
Para funciones y subrutinas en módulos, cualquier cosa que use
s ese módulo puede ver automáticamente esas interfaces; las interfaces se generan cuando se compila el módulo (esa información, entre otras cosas, va al archivo .mod que se genera cuando compilas un módulo). Así que no necesitas escribirlo tú mismo. Del mismo modo, cuando utiliza un CONTAIN
ed subprograma (que, de acuerdo con MSB, me parece más confuso que útil; se consideran mucho mejor como cierres o subrutinas anidadas que subrutinas externas), el programa principal ya puede ‘ver’ la interfaz explícitamente y no necesita que lo escribas para ello.
Los bloques de interfaz son para cuando no puedo haga esto: cuando el compilador no pueda generar la interfaz explícita para usted, o cuando desee algo diferente de lo que se proporciona. Un ejemplo es cuando se usa la interoperabilidad de C-Fortran en Fortran 2003. En ese caso, el código de Fortran se vincula con alguna biblioteca de C (por ejemplo) y no tiene forma de generar una interfaz de Fortran correcta para la rutina de C para usted; tiene que hágalo usted mismo, escribiendo su propio bloque de interfaz.
Otro ejemplo es cuando ya conoce las interfaces de las subrutinas, pero desea crear una nueva interfaz para “ocultar” las subrutinas detrás; por ejemplo, cuando tiene una rutina que opera con (digamos) números enteros y otra con números reales. , y desea poder llamar al mismo nombre de rutina en cualquiera y dejar que el compilador lo resuelva en función de los argumentos. Tales construcciones se denominan rutinas genéricas y existen desde Fortran 90. En ese caso, crea una interfaz explícitamente para esta nueva rutina genérica y enumera las interfaces para las rutinas “reales” dentro de ese bloque de interfaz.