Zoeken…


Opmerkingen

Functies en subroutines zijn in combinatie met modules de hulpmiddelen om een programma in eenheden op te splitsen. Dit maakt het programma beter leesbaar en beheersbaar. Elk van deze eenheden kan worden beschouwd als onderdeel van de code die, idealiter, afzonderlijk zou kunnen worden gecompileerd en getest. De hoofdprogramma's kunnen dergelijke subprogramma's (functies of subroutines) aanroepen (of aanroepen) om een taak te volbrengen.

Functies en subroutines zijn verschillend in de volgende zin:

  • Functies retourneren een enkel object en veranderen meestal de waarden van de argumenten niet (dwz ze werken net als een wiskundige functie!);
  • Subroutines voeren meestal een meer gecompliceerde taak uit en wijzigen gewoonlijk hun argumenten (indien aanwezig), evenals andere variabelen (bijv. Die welke zijn gedeclareerd in de module die de subroutine bevat).

Functies en subroutines vallen gezamenlijk onder de naam procedures . (In het volgende zullen we het werkwoord "aanroep" gebruiken als synoniem van "aanroepen", zelfs als technisch de aan te call procedures subroutine , terwijl function als rechterkant van de toewijzing of in uitdrukkingen verschijnen.)

Syntaxis van de functie

Functies kunnen worden geschreven met behulp van verschillende soorten syntaxis

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

Functies retourneren waarden via een functieresultaat . Tenzij de functie-instructie een result heeft, heeft het result de functie dezelfde naam als de functie. Met result het functieresultaat dat gegeven door het result . In elk van de eerste twee voorbeelden hierboven wordt het functieresultaat gegeven door name ; in de derde door res .

Het functieresultaat moet worden gedefinieerd tijdens de uitvoering van de functie.

Met functies kunnen enkele speciale voorvoegsels worden gebruikt.

Pure functie betekent dat deze functie geen bijwerking heeft:

pure real function square(x)
  real, intent(in) :: x
  square = x * x
end function

Elementaire functie wordt gedefinieerd als scalaire operator, maar kan worden opgeroepen met array als actueel argument, in welk geval de functie elementair wordt toegepast. Tenzij het impure voorvoegsel (geïntroduceerd in Fortran 2008) is opgegeven, is een elementaire functie ook een pure functie.

elemental real function square(x)
  real, intent(in) :: x
  square = x * x
end function

Retourverklaring

De return instructie kan worden gebruikt om de functie en subroutine af te sluiten. In tegenstelling tot veel andere programmeertalen wordt het niet gebruikt om de retourwaarde in te stellen.

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

Deze functie voert een iteratieve berekening uit. Als de waarde van f negatief wordt, retourneert de functie waarde -1000.

Recursieve procedures

In Fortran moeten functies en subroutines expliciet als recursief worden verklaard, als ze zichzelf weer direct of indirect moeten noemen. Zo kan een recursieve implementatie van de Fibonacci-serie er zo uitzien:

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

Een ander voorbeeld is toegestaan om faculteit te berekenen:

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

Opdat een functie zichzelf recursief zou kunnen verwijzen, moet de definitie het result achtervoegsel gebruiken. Het is niet mogelijk dat een functie zowel recursive als elemental .

De bedoeling van dummyargumenten

Het kenmerk intent van een dummy-argument in een subroutine of functie verklaart het beoogde gebruik. De syntaxis is er een van

intent(IN)
intent(OUT)
intent(INOUT)

Overweeg bijvoorbeeld deze functie:

real function f(x)
  real, intent(IN) :: x

  f = x*x
end function

De intent(IN) specificeert dat de (niet-pointer) dummy argument x niet kan worden bepaald of worden undefined gehele functie of de initialisatie. Als een pointer dummy-argument het kenmerk intent(IN) , is dit van toepassing op de associatie.

intent(OUT) voor een niet-pointer dummy-argument betekent dat dummy-argument ongedefinieerd wordt bij aanroep van het subprogramma (behalve voor componenten van een afgeleid type met standaardinitialisatie) en moet worden ingesteld tijdens de uitvoering. Het feitelijke argument dat als dummyargument wordt doorgegeven, moet definieerbaar zijn: het doorgeven van een benoemde of letterlijke constante, of een uitdrukking, is niet toegestaan.

Op dezelfde manier als hiervoor, wordt de associatiestatus van de aanwijzer ongedefinieerd als een pointer dummy-argument intent(OUT) is. Het eigenlijke argument hier moet een pointervariabele zijn.

intent(INOUT) geeft aan dat het eigenlijke argument definieerbaar is en geschikt is voor zowel het doorgeven als retourneren van gegevens uit de procedure.

Ten slotte kan een dummyargument zonder het kenmerk intent zijn. Het gebruik van zo'n dummyargument wordt beperkt door het feitelijk doorgegeven argument.

Overweeg bijvoorbeeld

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

Het argument i kan geen intent kenmerk hebben dat beide subroutine-aanroepen van het hoofdprogramma toestaat.

Verwijzen naar een procedure

Om een functie of subroutine nuttig te maken, moet hiernaar worden verwezen. Naar een subroutine wordt verwezen in een call statement

call sub(...)

en een functie binnen een uitdrukking. Anders dan in veel andere talen, vormt een uitdrukking geen volledige instructie, dus een functieverwijzing wordt vaak gezien in een toewijzingsinstructie of op een andere manier gebruikt:

x = func(...)
y = 1 + 2*func(...)

Er zijn drie manieren om een procedure aan te wijzen waarnaar wordt verwezen:

  • als de naam van een procedure of procedurewijzer
  • een procedurecomponent van een afgeleid type object
  • een type gebonden procedure bindende naam

De eerste kan worden gezien als

procedure(), pointer :: sub_ptr=>sub
call sub()   ! With no argument list the parentheses are optional
call sub_ptr()
end

subroutine sub()
end subroutine

en de laatste twee als

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

Voor een procedure met dummy-argumenten vereist de verwijzing overeenkomstige werkelijke argumenten, hoewel optionele dummy-argumenten mogelijk niet worden gegeven.

Overweeg de subroutine

subroutine sub(a, b, c)
  integer a, b
  integer, optional :: c
end subroutine

Hiernaar kan op de volgende twee manieren worden verwezen

call sub(1, 2, 3)   ! Passing to the optional dummy c
call sub(1, 2)      ! Not passing to the optional dummy c

Dit is zogenaamde positiereferentie : de feitelijke argumenten zijn gekoppeld op basis van de positie in de argumentlijsten. Hier wordt de dummy a geassocieerd met 1 , b met 2 en c (indien gespecificeerd) met 3 .

Als alternatief kan trefwoordverwijzing worden gebruikt wanneer voor de procedure een expliciete interface beschikbaar is

call sub(a=1, b=2, c=3)
call sub(a=1, b=2)

die hetzelfde is als hierboven.

Met zoekwoorden kunnen de feitelijke argumenten echter in willekeurige volgorde worden aangeboden

call sub(b=2, c=3, a=1)
call sub(b=2, a=1)

Positionele en trefwoordreferenties kunnen beide worden gebruikt

call sub(1, c=3, b=2)

zolang een trefwoord wordt gegeven voor elk argument na de eerste verschijning van een trefwoord

call sub(b=2, 1, 3)  ! Not valid: all keywords must be specified

De waarde van trefwoordverwijzingen is met name uitgesproken wanneer er meerdere optionele dummy-argumenten zijn, zoals hieronder te zien als in de subroutine-definitie hierboven b ook optioneel was

call sub(1, c=3)  ! Optional b is not passed

De argumentlijsten voor typegebonden procedures of componentprocedure-verwijzingen met een doorgegeven argument worden afzonderlijk beschouwd.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow