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.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow