Escopo, associação e ocultação de informações no Fortran 90
Essa pergunta está relacionada à chamada e sub-rotinas no Fortran 90. Estou bastante confuso sobre as regras para associação de host / uso / argumentos; Tenho problemas para entender a lógica do escopo que resulta dessas regras. Talvez a maneira mais simples de expor meu problema seja explicar o que eu gostaria de alcançar e por quê.
Gostaria de atender a dois requisitos de design:
(i) Uma sub-rotina de chamada apenas permite que a sub-rotina chamada acesse suas entidades que são passadas como argumentos, nenhuma outra. (ii) Uma sub-rotina chamada não permite que uma sub-rotina de chamada acesse qualquer uma das entidades que define localmente.
Se uma imagem ajudar, eu posso fornecer uma. Eu gostaria de poder pensar na chamada e nas sub-rotinas chamadas como duas salas conectadas por um canal que eles usam para passar ou retornar argumentos. Eu gostaria que essa associação de argumentos fosse o único meio pelo qual duas sub-rotinas pudessem influenciar uma a outra. Acredito que um código que atenda a esses requisitos será mais robusto aos efeitos colaterais. Se eu estiver enganado com essa idéia, ficaria grato por ser explicado o porquê. Se houver uma forte razão pela qual esses requisitos não devem ser desejados, eu também ficaria feliz em saber.
2Certamente, o fortran 90 oferece a possibilidade de usar módulos e a opção 'only'. Por exemplo, pode-se fazer o seguinte:
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
!………
Com certeza, my_sub_a poderá, no máximo, acessar as entidades de my_mod_b para as quais my_sub_b é uma unidade de escopo. Mas será capaz de acessar entidades de my_sub_b além da lista de argumentos que está passando? Em particular, my_sub_a poderá acessar entidades locais para my_sub_b? Por outro lado, a associação de uso permite que my_sub_b acesse entidades de my_sub_a diferentes daquelas transmitidas como argumentos reais?
3A seguinte construção de "módulo de buffer" é suficiente para atender aos requisitos do 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
!………
4Existe alguma construção mais simples para alcançar os objetivos do # 1?
5Seguindo as sugestões propostas por Ross e Vladimir F,
uma possibilidade poderia ser:
(i ') para ter uma correspondência individual entre módulos e sub-rotinas,
(ii ') declarar variáveis locais no módulo em vez da sub-rotina; então é possível marcar variáveis locais como "privadas".
Apenas para ter certeza de que entendi direito, aqui está um programa trivial que ilustra (i ') e (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
Neste exemplo, a única entidade de sub_a que sub_b pode acessar é v0 (associação de argumentos); u0 permanecerá oculto para sub_b. Por outro lado, a tag 'private' garante que a variável w0 permaneça fora do escopo de sub_a, mesmo que sub_a use o sub_b_module. Isso está certo?
@ Ross: Obrigado por apontar uma postagem anterior onde a associação é herdada. No entanto, minha impressão é que ele aborda apenas metade do meu problema; a construção discutida nesse post ilustra como é possível impedir que uma unidade de programa chamador acesse as entidades de uma unidade de programa chamada que deve permanecer oculta (opções 'use only' e / ou 'private'), mas não consigo afirmar com certeza que as entidades da unidade de programa chamador que não estão associadas a argumentos permanecerão inacessíveis para a unidade de programa chamada.