
I moduli sono il punto d’arrivo di una linea di sviluppo antica. Probabilmente conviene esaminarne i vari componenti per comprenderne l’utilità e la bellezza.
Le procedure, funzioni e subroutine, hanno diversi scopi:
- riusare blocchi di codice;
- ripetere operazioni con set diversi di dati;
- evitare conflitti tra le variabili
- semplificare lo sviluppo (divide et impera).
Il loro posto naturale sono i moduli; inoltre questi possono contenere costanti (parameter), variabili, arrays, structures. In questo caso il modulo supera il common, in modo più flessibile. Eccone un esempio.
program e_com !esempio d'uso di common
implicit none
common /my_common/ intv, realv, complv
integer :: intv
real :: realv
complex :: complv
intv = 21
realv = 24.6
complv = (3, 4)
print *, 'inizio'
print *, intv, realv
print *, complv
call doppio
print *, 'dopo'
print *, intv, realv
print *, complv
end
subroutine doppio
implicit none
common /my_common/ intv, realv, complv
integer :: intv
real :: realv, re, im
complex :: complv
character :: nl = new_line(' ')
print *, nl, 'doppio', nl
intv = 2 * intv
realv = 2 * realv
re = 2.0 * real(complv)
im = 2.0 * aimag(complv)
complv = complex(re, im)
end

Lo stresso programma riscritto usando un modulo
program e_mod !esempio d'uso di modulo use m_mod implicit none intv = 21 realv = 24.6 complv = (3, 4) print *, 'inizio' print *, intv, realv print *, complv call doppio print *, 'dopo' print *, intv, realv print *, complv end
e
module m_mod
implicit none
save
integer :: intv
real :: realv
complex :: complv
contains
subroutine doppio
real :: re, im
character :: nl = new_line(' ')
print *, nl, 'doppio', nl
intv = 2 * intv
realv = 2 * realv
re = 2.0 * real(complv)
im = 2.0 * aimag(complv)
complv = complex(re, im)
end subroutine doppio
end module m_mod

Con i moduli si possono scrivere procedure polimorfe, simili a quelle predefinite. Fin dall’antichità (quasi) si può usare, per esempio, max() al posto di amax0(), amax1(), max0() e max1(). Adesso si possono costruire! Ecco un esempio, preso da TACC, la funzione swap().
module mod_swap
public swap
private swap_real, swap_integer
interface swap
module procedure swap_real, swap_integer
end interface
contains
subroutine swap_real(x, y)
real :: x, y, t
t = x
x = y
y = t
end subroutine swap_real
subroutine swap_integer(i, j)
integer :: i, j, k
k = i
i = j
j = k
end subroutine swap_integer
end module mod_swap
program p_swap use mod_swap real :: a = 3., b = 4. integer :: i = 1, j = 2 call swap(a, b) print *, a, b call swap(i, j) print *, i, j end

Posso definire operatori, ecco .plus. che fa la somma di due interi
module mod_op
public :: operator(.plus.)
private :: f_plus
interface operator(.plus.)
module procedure f_plus
end interface
contains
function f_plus(x, y) result(res)
integer, intent(in) :: x, y
integer :: res
res = x + y
end function
end module
program p_op use mod_op i = 3 j = 5 print *, i, j, i .plus. j end

Esistono inoltre le funzioni elemental, questa è una parola magica che estende la funzione agli array
module m_quad
contains
elemental function quad(x) result (q)
real, intent(in) :: x
real :: q
q = x * x
end function
end module
program p_quad use m_quad real :: t = 12. real, dimension(3) :: v = [1., 2., 3.] print *, t, quad(t) print *, v print *, quad(v) end

Durante la compilazione di un modulo viene creato un file .mod. Devo ancora capire quando viene utilizzato, se si rimuove l’eseguibile funziona ugualmente. Sono file di testo, che iniziano in questo modo:
GFORTRAN module version '6' created from m_mod.f08 on Mon Jun 25 09:10:02 2012
MD5:09d3ef60d0503441cdee588ae159073e -- If you edit this, you'll get what you deserve.
Prossimamente, forse

Commenti
Sta diventando un linguaggio molto bello!!