Ich hoffe, Fortran eine populäre Syntax wie
subroutine mysub(x, val = -1)
integer, optional :: val
oder in einem Fortran-Stil
subroutine mysub(x, val)
integer, optional :: val = -1 !! not SAVE attribute intended
aber dies scheint nicht unterstützt (Stand 2016) zu unterstützen. Also müssen einige Workarounds von Seiten der Benutzer durchgeführt werden ...
In meinem Fall nach Versuch und Fehler, ließ ich mich auf die optionale Dummy-Argument Anbringen eines Strich nach unten, so etwas wie das Tun (*)
subroutine mysub(x, val_)
integer, optional :: val_
integer val
Andere Leute scheinen das Gegenteil Muster zu mögen (dh Dummy-Variable =>sep
, lokale Variable =>sep_
, siehe beispielsweise split() in StringiFor). Wie in this line gesehen, ist der kürzeste Weg, um den Standardwert zu setzen
val = -1 ; if (present(val_)) val = val_
Aber weil auch diese Linie etwas ausführlich ist, definiere ich in der Regel einen Makro wie
#define optval(x,opt,val) x = val; if (present(opt)) x = opt
in einer gemeinsamen Header-Datei und die Nutzung als
subroutine mysub(x, val_, eps_)
integer :: x
integer, optional :: val_
real, optional :: eps_
integer val
real eps
optval(val, val_, -1)
optval(eps, eps_, 1.0e-5)
print *, "x=", x, "val=", val, "eps=", eps
endsubroutine
...
call mysub(100)
call mysub(100, val_= 3)
call mysub(100, val_= 3, eps_= 1.0e-8)
aber ich glaube, das von elegant noch weit ist und nicht mehr als eine Anstrengung zu machen, etwas weniger fehleranfällig (indem sie die gewünschten Variablennamen in der Körper des Unterprogramms).
Eine andere Lösung für eine sehr „großen“ Unterprogramm könnte sein, einen abgeleiteten Typ übergeben, die alle Argumente verbleibenden Schlüsselwort enthält. Zum Beispiel
#define getkey(T) type(T), optional :: key_; type(T) key; if (present(key_)) key = key_
module mymod
implicit none
type mysub_k
integer :: val = -1
real :: eps = 1.0e-3
endtype
contains
subroutine mysub(x, seed_, key_)
integer :: x
integer, optional :: seed_
integer :: seed
getkey(mysub_k) !! for all the remaining keyword arguments
optval(seed, seed_, 100)
print *, x, seed, key% val, key% eps
endsubroutine
endmodule
program main
use mymod, key => mysub_k
call mysub(10)
call mysub(20, key_= key(val = 3))
call mysub(30, seed_=200, key_= key(eps = 1.0e-8)) ! ugly...
endprogram
Dies könnte ein bisschen nahe sein, was von einigen dynamischen Sprachen unter der Haube getan wird, aber das ist wieder weit von elegant in der obigen Form ...
(*) Ich weiß, dass es oft als hässlich angesehen wird, CPP-Makros zu verwenden, aber IMO hängt davon ab, wie sie verwendet werden; wenn sie auf begrenzte Fortran-Syntax beschränkt sind, halte ich das für sinnvoll (weil es in Fortran keine Metaprogrammiermöglichkeit gibt); andererseits sollte die Definition programmabhängiger Konstanten oder Verzweigungen wahrscheinlich vermieden werden. Auch ich denke, es wäre mächtiger sein Python zu verwenden, etc zu flexibleren Preprozessoren zu machen (zB PreForM.py und fypp und so weiter), beispielsweise eine Syntax wie subroutine sub(val = -1)
Die erste Lösung ist, was ich in der ursprünglichen Frage veröffentlicht - Ändern der Namenskonvention macht es nicht wirklich ein neues Muster. Die zweite Lösung ist leider ungültiger Code, wenn es mehr als ein optionales Argument gibt, da fortran keine Mischdeklaration und Ausführungscode zulässt - während für ein einzelnes optionales Argument die Verwendung eines Makros wahrscheinlich nicht ausreicht, um die Dunkelheit zu rechtfertigen . – kdb
Hallo, weil die aktuellen Fortran-Standards keine echte "Lösung" erlauben (wie von Vladimir unten vorgeschlagen), gibt es keinen anderen Weg, als eine lokale Variable mit ähnlichem Namen zu verwenden, und ich dachte, du suchst nach systematischen (weniger fehleranfällige Workarounds. RE der zweite Punkt, der obige Code ist gültig (Sie können es versuchen) und Sie können auch andere übliche optionale Variablen vor key_ hinzufügen. Der Punkt ist, dass setkey() nach allen anderen Deklarationen kommen sollte, aber das ist natürlich, weil diese Art von Schlüsselwortargumenten normalerweise hinter allen optionalen Argumenten steht. – roygvib
Mein Zweck ist es auch, meine Praxis zu präsentieren, niemals um ihre Verwendung zu befürworten. Was noch wichtiger ist, meine Absicht ist es, hervorzuheben, wie die aktuelle Fortran-Syntax in einigen Teilen begrenzt ist und den Benutzer dazu zwingt, einen ziemlich ausführlichen/langwierigen Code zu schreiben. – roygvib