Alcance, asociación e información oculta en Fortran 90
Esta pregunta se refiere a las subrutinas llamadas y llamadas en Fortran 90. Estoy bastante confundido acerca de las reglas para la asociación host / uso / argumentos; Tengo problemas para comprender la lógica de alcance que resulta de estas reglas. Quizás la forma más sencilla de exponer mi problema es explicar lo que me gustaría lograr y por qué.
Me gustaría cumplir con dos requisitos de diseño:
(i) Una subrutina de llamada solo permite que la subrutina llamada acceda a sus entidades que se pasan como argumentos, no otra. (ii) Una subrutina llamada no permite que una subrutina llamante acceda a ninguna de las entidades que define localmente.
Si una imagen ayuda, puedo proporcionar una. Me gustaría poder pensar en la llamada y las subrutinas llamadas como dos habitaciones conectadas por un canal que utilizan para pasar o devolver argumentos. Me gustaría que esta asociación de argumentos sea el único medio por el cual dos subrutinas podrían tener influencia entre sí. Creo que un código que cumpla con estos requisitos será más robusto a los efectos secundarios. Si me equivoco con esta idea, agradecería que me explicaran por qué. Si hay una razón sólida por la cual estos requisitos no deberían desearse, también me complacería saberlo.
2Ciertamente, fortran 90 ofrece la posibilidad de usar módulos y la opción "solo". Por ejemplo, uno puede hacer lo siguiente:
module my_mod_a
contains
subroutine my_sub_a
use my_mod_b, only: my_sub_b
…
call my_sub_b(arg_list_b)
…
end subroutine my_sub_a
end module my_mod_a
!………
module my_mod_b
contains
subroutine my_sub_b(arg_list_b’)
do stuff with arg_list_b’
end my_sub_b
…
end module my_mod_b
!………
Efectivamente, my_sub_a como máximo podrá acceder a aquellas entidades de my_mod_b para las cuales my_sub_b es una unidad de alcance. Pero, ¿podrá acceder a entidades de my_sub_b que no sean la lista de argumentos que está pasando? En particular, ¿my_sub_a podrá acceder a entidades que son locales a my_sub_b? Por el contrario, ¿la asociación de uso permite que my_sub_b acceda a entidades de my_sub_a diferentes de las que se pasan como argumentos reales?
3¿Es suficiente la siguiente construcción del "módulo de almacenamiento intermedio" para cumplir con los requisitos del n. ° 1?
module my_mod_a
contains
subroutine my_sub_a
use my_mod_b_shell, only: my_sub_b_shell
…
call my_sub_b_shell(arg_list_b)
…
end subroutine my_sub_a
end module my_mod_a
!………
module my_mod_b_shell
contains
subroutine my_sub_b_shell(arg_list_b’)
!passes arguments, does not do anything else
use my_mod_b, only: my_sub_b
call my_sub_b(arg_list_b’)
end my_sub_b_shell
end module my_mod_b_shell
!………
module my_mod_b
contains
subroutine my_sub_b(arg_list_b’)
do stuff with arg_list_b’
end my_sub_b
…
end module my_mod_b
!………
4¿Hay alguna construcción más simple para lograr los objetivos del # 1?
5Siguiendo las sugerencias propuestas por Ross y Vladimir F,
Una posibilidad podría ser:
(i ’) para tener una correspondencia uno a uno entre módulos y subrutinas,
(ii ’) para declarar variables locales en el módulo en lugar de la subrutina; uno puede etiquetar las variables locales como "privadas".
Solo para asegurarme de que he entendido bien, aquí hay un programa trivial que ilustra (i ") y (ii"):
program main
use sub_a_module
implicit none
double precision :: x
x=0.0d+0
write(*,*) 'x ante:',x
call sub_a(x)
write(*,*) 'x post:',x
end program main
!-------------------------------------------------
module sub_a_module
double precision, private :: u0
double precision, private :: v0
contains
!.-.-.-.-.-.-.-.-
subroutine sub_a(x)
use sub_b_module
implicit none
double precision :: x
u0=1.0d+0
v0=2.0d+0
call sub_b(v0)
x=x+u0+v0
end subroutine sub_a
!.-.-.-.-.-.-.-.-
end module sub_a_module
!-------------------------------------------------
module sub_b_module
double precision, private :: w0
contains
!.-.-.-.-.-.-.-.-
subroutine sub_b(v)
implicit none
double precision :: v
w0=1.0d-1
v=v+w0
end subroutine sub_b
!.-.-.-.-.-.-.-.-
end module sub_b_module
En este ejemplo, la única entidad de sub_a a la que puede acceder sub_b es v0 (asociación de argumento); u0 permanecerá oculto a sub_b. Por el contrario, la etiqueta 'privada' garantiza que la variable w0 permanezca fuera del alcance de sub_a incluso si sub_a usa el sub_b_module. ¿Está bien?
@Ross: Gracias por señalar una publicación anterior donde se hereda la asociación. Sin embargo, mi impresión es que solo aborda la mitad de mi problema; la construcción discutida en esa publicación ilustra cómo se puede evitar que una unidad de programa llamante acceda a entidades de una unidad de programa llamada que deberían permanecer ocultas (opciones 'usar solo' y / o 'privadas'), pero no puedo afirmar con certeza que las entidades de la unidad de programa llamante que no están asociadas a argumentos permanecerán inaccesibles para la unidad de programa llamada.