Sök…


Anmärkningar

Funktioner och subroutiner , tillsammans med moduler , är verktygen för att dela upp ett program i enheter. Detta gör programmet mer läsbart och hanterbart. Var och en av dessa enheter kan betraktas som en del av koden som helst skulle kunna sammanställas och testas isolerat. Huvudprogrammet kan anropa (eller åberopa) sådana delprogram (funktioner eller subroutiner) för att utföra en uppgift.

Funktioner och subroutiner är olika i följande mening:

  • Funktioner returnerar ett enda objekt och - vanligtvis - ändrar inte värdena på dess argument (dvs. de fungerar precis som en matematisk funktion!);
  • Subroutiner utför vanligtvis en mer komplicerad uppgift och de ändrar vanligtvis sina argument (om något finns), såväl som andra variabler (t.ex. de som deklareras i modulen som innehåller subroutinen).

Funktioner och subroutiner omfattas gemensamt av procedurer . (I det följande kommer vi att använda verbet "samtal" som synonym för "åkalla" även om tekniskt sett är procedurerna som ska call upp subroutine , medan function s visas som höger sida av uppdraget eller i uttryck.)

Funktionssyntax

Funktioner kan skrivas med flera typer av syntax

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

Funktioner returnerar värden genom ett funktionsresultat . Såvida inte funktionsklaringen har en result har funktionens resultat samma namn som funktionen. Med result är funktionsresultatet det som ges av result . I vart och ett av de två första exemplen ovan ges funktionsresultatet med name ; i den tredje av res .

Funktionsresultatet måste definieras under körning av funktionen.

Funktioner gör det möjligt att använda vissa speciella prefix.

Ren funktion betyder att denna funktion inte har någon biverkning:

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

Elementarfunktion definieras som skaläroperatör men den kan åberopas med matris som faktiskt argument, i vilket fall funktionen kommer att tillämpas elementärt. Om inte det impure prefixet (introducerat i Fortran 2008) anges är en elementär funktion också en ren funktion.

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

Return statement

Den return uttalande kan användas för att avsluta funktionen och subrutin. Till skillnad från många andra programmeringsspråk används det inte för att ställa in returvärdet.

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

Denna funktion utför en iterativ beräkning. Om värdet på f blir negativt returnerar funktionen värdet -1000.

Rekursiva förfaranden

I Fortran-funktioner och subroutiner måste deklareras uttryckligen som rekursiva , om de ska kalla sig själva igen, direkt eller indirekt. Således kan en rekursiv implementering av Fibonacci-serien se ut så här:

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

Ett annat exempel är tillåtet att beräkna factorial:

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

För att en funktion ska direkt rekursivt referera till sig själv måste dess definition använda result . Det är inte möjligt för en funktion att vara både recursive och elemental .

Syftet med dummy-argument

intent för ett dummy-argument i en subroutine eller funktion förklarar dess avsedda användning. Syntaxen är antingen en av

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

Tänk till exempel på den här funktionen:

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

  f = x*x
end function

intent(IN) specificerar att (icke-pekaren) dummy-argumentet x aldrig får definieras eller bli odefinierat under hela funktionen eller dess initialisering. Om ett pekar-dummy-argument har attributens intent(IN) , gäller detta dess associering.

intent(OUT) för ett icke-pekande dummy-argument betyder att dummy-argumentet blir odefinierat vid anrop av delprogrammet (förutom alla komponenter av en härledd typ med standardinitialisering) och ska ställas in under körning. Det faktiska argumentet som skickas som dummy-argument måste vara definierbart: att passera en namngiven eller bokstavlig konstant, eller ett uttryck, är inte tillåtet.

På samma sätt som tidigare, om ett pekare-dummy-argument är intent(OUT) blir pekarens associeringsstatus odefinierad. Det faktiska argumentet här måste vara en pekvariabel.

intent(INOUT) anger att det faktiska argumentet är definierbart och är lämpligt för både att skicka in och returnera data från proceduren.

Slutligen kan ett övnings argument vara utan intent attribut. Ett sådant dummy-argument har dess användning begränsat av det faktiska argumentet som har gått.

Tänk till exempel

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

Argumentet i kan inte ha något intent attribut som tillåter båda subroutine samtal i huvudprogrammet.

Hänvisar ett förfarande

För att en funktion eller subrutin ska vara användbar måste den hänvisas. En subroutine hänvisas till i ett call

call sub(...)

och en funktion inom ett uttryck. Till skillnad från på många andra språk bildar ett uttryck inte ett fullständigt uttalande, så en funktionsreferens ses ofta i ett uppdragsuttalande eller används på något annat sätt:

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

Det finns tre sätt att beteckna en procedur som refereras till:

  • som namnet på en procedur eller procedurpekare
  • en procedurkomponent för ett härledt typobjekt
  • en typbunden procedur som binder namn

Den första kan ses som

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

subroutine sub()
end subroutine

och de sista två som

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

För en procedur med dummy-argument kräver referensen motsvarande faktiska argument, även om valfria dummy-argument kanske inte anges.

Tänk på subrutinen

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

Det kan hänvisas till detta på följande två sätt

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

Detta är så kallad positionsreferens : de faktiska argumenten är associerade baserat på positionen i argumentlistorna. Här är dummy a associerad med 1 , b med 2 och c (när det anges) med 3 .

Alternativt kan sökordsreferenser användas när proceduren har ett tydligt gränssnitt tillgängligt

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

vilket är samma som ovan.

Men med nyckelord kan de faktiska argumenten erbjudas i valfri ordning

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

Båda hänvisningar till positioner och nyckelord kan användas

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

så länge ett nyckelord anges för varje argument efter det första nyckelordet visas

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

Värdet på nyckelordreferenser är särskilt uttalat när det finns flera valfria dummy-argument, som ses nedan om i subroutindefinitionen ovan b också var valfritt

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

Argumentlistorna för typbundna procedurer eller komponentprocesspekare med ett godkänt argument beaktas separat.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow