Escopo, associação e ocultação de informações no Fortran 90

1

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.

2

Certamente, 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?

3

A 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
!………
4

Existe alguma construção mais simples para alcançar os objetivos do # 1?

5

Seguindo 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.

questionAnswers(2)

yourAnswerToTheQuestion