Unità di programma: Argomenti per le chiamate a subroutine e function

Le chiamate a subroutine e function in f90 presentano alcune novità:
Gli argomenti formali dei sottoprogrammi possono avere uno degli attributi INTENT(IN), INTENT(OUT) o INTENT(INOUT) che indicano come intendiamo trattare quei parametri:
  • INTENT(IN) significa che la variabile è da utilizzarsi solo in ingresso, per cui viene segnalato un errore in compilazione se la subroutine tenta di modificarla
  • INTENT(OUT) significa che la variabile è da utilizzarsi solo in uscita, per cui è formalmente sbagliato (ma questo il compilatore non è sempre in grado di verificarlo) se la subroutine usa il valore fornito in ingresso e/o se non assegna nessun valore alla variabile, e inoltre viene segnalato un errore in compilazione se il corrispondente parametro nell'unità chiamante è una costante
  • INTENT(INOUT) significa che la variabile è da utilizzarsi sia in ingresso che in uscita, per cui la subroutine può utilizzare il suo valore ed è moralmente tenuta a riassegnarlo nel corso dell'esecuzione
  • se nessun INTENT è specificato, non saranno fatti controlli sull'uso dei parametri, ma ciò non differisce in pratica dal caso INTENT(INOUT)
MODULE intento
IMPLICIT NONE
CONTAINS

SUBROUTINE accumula_area(r, area_tot, area)
REAL, INTENT(IN) :: r
REAL, INTENT(INOUT) :: area_tot
REAL, INTENT(OUT) :: area

REAL, larea

!r = 0. ! vietato!
!larea = area ! vietatino
area = r**2*3.14
area_tot = area_tot+area

END SUBROUTINE accumula_area

END MODULE intento

PROGRAM test_intento
USE intento
IMPLICIT NONE

REAL, PARAMETER :: a1 = 4.
REAL :: r, a, at = 0.

r = 2.
CALL accumula_area(r, at, a)
PRINT*,a,at
CALL accumula_area(3., at, a)
PRINT*,a,at
!CALL accumula_area(r, at, 3.) ! vietato!
!CALL accumula_area(r, 3., a) ! vietato?
!CALL accumula_area(r, a1, a) ! vietato?

END PROGRAM test_intento

Le subroutine possono avere argomenti opzionali e essere richiamate in modalità keyword:
  • gli argomenti opzionali sono quelli specificati nella subroutine dall'attributo OPTIONAL; essi devono essere gli ultimi nell'elenco, cioè non possono essere seguiti da argomenti non opzionali
  • esiste la funzione logica intrinseca PRESENT() per verificare se ciascun parametro opzionale sia stato effettivamente passato dall'unità di programma chiamante
  • attenzione: ogni operazione che coinvolge argomenti opzionali deve essere eseguita sotto la condizione che il corrispondente argomento sia PRESENT(), altrimenti il comportamento è imprevedibile, unica eccezione, un argomento opzionale può essere passato a sua volta come argomento opzionale ad un altro sottoprogramma senza effettuare alcun controllo su di esso
  • l'indicazione di tutti o parte degli argomenti in una chiamata a subroutine può essere effettuata nella modalità keyword, anziché posizionale, con la ovvia condizione che una volta iniziata la modalità keyword non si può tornare alla modalità posizionale
  • la modalità keyword ha senso principalmente in associazione con multipli argomenti opzionali, ma può essere utilizzata anche per argomenti obbligatorî.
MODULE argomenti

SUBROUTINE misto(a,b,c,d)
INTEGER :: a
REAL :: b
INTEGER, OPTIONAL :: c
REAL, OPTIONAL :: d

PRINT*,a,b
IF (PRESENT(c)) PRINT*,'Ho ricevuto c:',c
IF (PRESENT(d)) PRINT*,'Ho ricevuto d:',d

END SUBROUTINE misto

END MODULE argomenti

PROGRAM test_argomenti
USE argomenti

CALL misto(2,3.,4)
CALL misto(2,3.,d=6.)
CALL misto(b=3.,a=2,d=6.)

END PROGRAM test_argomenti

Tutte le innovazioni presentate ora funzionano se le unità di programma in cui sono utilizzate si trovano all'interno di un MODULE o hanno una corrispondente INTERFACE nota al programma chiamante. In tale caso viene controllato, al momento della compilazione, anche il corretto abbinamento tra numero e tipo di argomenti passati al sottoprogramma.