Fortran
Procédures - Fonctions et sous-programmes
Recherche…
Remarques
Les fonctions et les sous - programmes , associés aux modules , sont les outils permettant de décomposer un programme en unités. Cela rend le programme plus lisible et gérable. Chacune de ces unités peut être considérée comme faisant partie du code qui, idéalement, pourrait être compilé et testé isolément. Le ou les programmes principaux peuvent appeler (ou appeler) de tels sous-programmes (fonctions ou sous-programmes) pour accomplir une tâche.
Les fonctions et les sous-programmes sont différents dans le sens suivant:
- Les fonctions renvoient un seul objet et - généralement - ne modifient pas les valeurs de ses arguments (c.-à-d. Qu'elles agissent comme une fonction mathématique!);
- Les sous-routines effectuent généralement une tâche plus compliquée et modifient généralement leurs arguments (le cas échéant), ainsi que d'autres variables (par exemple, celles déclarées dans le module contenant la sous-routine).
Les fonctions et les sous-programmes sont regroupés sous le nom de procédures . (Dans ce qui suit, nous utiliserons le verbe "call" comme synonyme de "invoke" même si techniquement les procédures à call
ed sont des subroutine
- subroutine
s, alors que les function
s apparaissent à droite de l'affectation ou dans des expressions.)
Syntaxe de la fonction
Les fonctions peuvent être écrites en utilisant plusieurs types de syntaxe
function name()
integer name
name = 42
end function
integer function name()
name = 42
end function
function name() result(res)
integer res
res = 42
end function
Les fonctions renvoient des valeurs via un résultat de fonction . À moins que l'instruction de la fonction n'ait une clause result
, le result
la fonction porte le même nom que la fonction. Avec result
le result
la fonction est celui donné par le result
. Dans chacun des deux premiers exemples ci-dessus, le résultat de la fonction est donné par name
; dans le troisième par res
.
Le résultat de la fonction doit être défini lors de l'exécution de la fonction.
Les fonctions permettent d'utiliser des préfixes spéciaux.
La fonction pure signifie que cette fonction n'a aucun effet secondaire:
pure real function square(x)
real, intent(in) :: x
square = x * x
end function
La fonction élémentaire est définie en tant qu'opérateur scalaire, mais elle peut être invoquée avec le tableau comme argument réel, auquel cas la fonction sera appliquée par élément. À moins que le préfixe impure
(introduit dans Fortran 2008) ne soit spécifié, une fonction élémentaire est également une fonction pure .
elemental real function square(x)
real, intent(in) :: x
square = x * x
end function
Déclaration de retour
L'instruction return
peut être utilisée pour quitter la fonction et la sous-routine. Contrairement à beaucoup d'autres langages de programmation, il n'est pas utilisé pour définir la valeur de retour.
real function f(x)
real, intent(in) :: x
integer :: i
f = x
do i = 1, 10
f = sqrt(f) - 1.0
if (f < 0) then
f = -1000.
return
end if
end do
end function
Cette fonction effectue un calcul itératif. Si la valeur de f
devient négative, la fonction renvoie la valeur -1000.
Procédures récursives
Dans Fortran, les fonctions et les sous-routines doivent être déclarées explicitement comme récursives , si elles doivent se rappeler, directement ou indirectement. Ainsi, une implémentation récursive de la série Fibonacci pourrait ressembler à ceci:
recursive function fibonacci(term) result(fibo)
integer, intent(in) :: term
integer :: fibo
if (term <= 1) then
fibo = 1
else
fibo = fibonacci(term-1) + fibonacci(term-2)
end if
end function fibonacci
Un autre exemple est autorisé à calculer factoriel:
recursive function factorial(n) result(f)
integer :: f
integer, intent(in) :: n
if(n == 0) then
f = 1
else
f = n * f(n-1)
end if
end function factorial
Pour qu'une fonction se réfère directement de manière récursive, sa définition doit utiliser le suffixe de result
. Il n'est pas possible qu'une fonction soit à la fois recursive
et elemental
.
L'intention des arguments factices
L'attribut d' intent
d'un argument factice dans une sous-routine ou une fonction déclare son utilisation prévue. La syntaxe est soit l'un des
intent(IN)
intent(OUT)
intent(INOUT)
Par exemple, considérez cette fonction:
real function f(x)
real, intent(IN) :: x
f = x*x
end function
L' intent(IN)
spécifie que l'argument factice (non pointeur) x
peut ne jamais être défini ou devenir indéfini pendant toute la fonction ou son initialisation. Si un argument factice de pointeur a l'attribut intent(IN)
, cela s'applique à son association.
intent(OUT)
pour un argument factice non-pointeur signifie que l'argument factice devient indéfini lors de l'appel du sous-programme (sauf pour les composants d'un type dérivé avec initialisation par défaut) et doit être défini lors de l'exécution. L'argument réel transmis en tant qu'argument factice doit être définissable: le passage d'une constante nommée ou littérale, ou d'une expression, n'est pas autorisé.
De même que précédemment, si un argument factice de pointeur est intent(OUT)
le statut d'association du pointeur devient indéfini. L'argument actuel doit être une variable de pointeur.
intent(INOUT)
spécifie que l'argument réel est définissable et convient à la fois pour transmettre et renvoyer des données de la procédure.
Enfin, un argument factice peut être sans l'attribut intent
. Un tel argument factice est limité par l'argument proprement dit.
Par exemple, considérez
integer :: i = 0
call sub(i, .TRUE.)
call sub(1, .FALSE.)
end
subroutine sub(i, update)
integer i
logical, intent(in) :: update
if (update) i = i+1
end subroutine
L'argument que i
ne peux avoir aucun attribut d' intent
qui permet les deux appels de sous-programme du programme principal.
Référencement d'une procédure
Pour qu'une fonction ou un sous-programme soit utile, il doit être référencé. Un sous-programme est référencé dans une déclaration d' call
call sub(...)
et une fonction dans une expression. Contrairement à de nombreux autres langages, une expression ne constitue pas une instruction complète, de sorte qu'une référence de fonction est souvent vue dans une instruction d'affectation ou utilisée d'une autre manière:
x = func(...)
y = 1 + 2*func(...)
Il existe trois façons de désigner une procédure référencée:
- comme nom d'un pointeur de procédure ou de procédure
- un composant de procédure d'un objet de type dérivé
- un nom de liaison de procédure liée au type
Le premier peut être vu comme
procedure(), pointer :: sub_ptr=>sub
call sub() ! With no argument list the parentheses are optional
call sub_ptr()
end
subroutine sub()
end subroutine
et les deux derniers comme
module mod
type t
procedure(sub), pointer, nopass :: sub_ptr=>sub
contains
procedure, nopass :: sub
end type
contains
subroutine sub()
end subroutine
end module
use mod
type(t) x
call x%sub_ptr() ! Procedure component
call x%sub() ! Binding name
end
Pour une procédure avec des arguments factices, la référence nécessite des arguments réels correspondants, bien que des arguments factices facultatifs puissent ne pas être donnés.
Considérons le sous-programme
subroutine sub(a, b, c)
integer a, b
integer, optional :: c
end subroutine
Cela peut être référencé des deux manières suivantes
call sub(1, 2, 3) ! Passing to the optional dummy c
call sub(1, 2) ! Not passing to the optional dummy c
C'est ce qu'on appelle le référencement de position : les arguments réels sont associés en fonction de la position dans les listes d'arguments. Ici, le mannequin a
est associé à 1
, b
avec 2
et c
(lorsque spécifié) avec 3
.
Alternativement, le référencement par mot - clé peut être utilisé lorsque la procédure dispose d'une interface explicite disponible
call sub(a=1, b=2, c=3)
call sub(a=1, b=2)
qui est le même que ci-dessus.
Cependant, avec des mots-clés, les arguments réels peuvent être proposés dans n'importe quel ordre.
call sub(b=2, c=3, a=1)
call sub(b=2, a=1)
Le référencement par position et par mot clé peut être utilisé
call sub(1, c=3, b=2)
tant qu'un mot-clé est donné pour chaque argument suite à la première apparition d'un mot-clé
call sub(b=2, 1, 3) ! Not valid: all keywords must be specified
La valeur du référencement par mot-clé est particulièrement prononcée lorsqu'il existe plusieurs arguments factices facultatifs, comme indiqué ci-dessous si, dans la définition de la sous-routine ci-dessus, b
étaient également facultatifs.
call sub(1, c=3) ! Optional b is not passed
Les listes d'arguments pour les procédures liées aux types ou les pointeurs de procédures de composants avec un argument passé sont considérées séparément.