In fortran können wir Standardargumente definieren. Wenn ein optionales Argument nicht vorhanden ist, kann es auch nicht festgelegt werden. Wenn Sie Argumente als Schlüsselwortargumente mit Standardwerten verwenden, führt dies zu umständlichen Konstrukten wie
%Vor% Persönlich stieß ich oft auf das Problem, versehentlich VAL
anstelle von AVAL
einzugeben, dh die Trennung zwischen dem Variablennamen in der Schnittstelle und dem initialisierten Wert im Code kann Laufzeitfehler verursachen - geschweige denn das Diese Art der Initialisierung ist ziemlich ausführlich.
Gibt es eine elegantere Möglichkeit, optionale Argumente mit einem Standardwert zu verwenden?
Beispiel Es wäre natürlicher, etwas wie
zu schreiben %Vor%, weil die VAL
vs AVAL
Verwirrung vermieden wird. Aber es ist nicht gültig, vermutlich, weil Fortran Argumente als Referenz übergibt und somit, wenn VAL
nicht in der CALL
-Anweisung vorhanden ist, kein Speicher mit VAL
verknüpft ist und VAL = -1
einen segfault verursachen würde.
Sie haben die Situation ziemlich gut beschrieben. Es gibt keinen anderen Weg, auf dem ich mich bewusst bin ( stellt sich heraus, dass ich es wirklich nicht wusste, siehe Gabe's Antwort ). Das Muster mit einer ähnlichen lokalen Variablen wird häufig verwendet. Die andere Möglichkeit ist, if (present()) else
überall zu setzen, aber das ist peinlich.
Der Punkt ist, dass es optionale Argumente sind, nicht Standard Argumente. Fortran hat keine Standardargumente. Das könnte besser gewesen sein, aber das ist nicht das, was die Komiteemitglieder in den 80ern bei der Vorbereitung von Fortran 90 gewählt haben.
Während ich mir das auch ansehe, habe ich herausgefunden, dass Sie tatsächlich etwas wie das vorgeschlagene Beispiel mit den Attributen OPTIONAL
und VALUE
machen können (zumindest mit gfortran, nicht sicher, wie verschiedene Compiler damit umgehen könnten). Zum Beispiel:
Dies wurde in Version 4.9 von gfortran implementiert. Und hier ist die relevante Erklärung in der Dokumentation für die Übergabe von Konventionen :
Bei OPTIONAL-Dummy-Argumenten wird ein abwesendes Argument mit NULL gekennzeichnet Zeiger, außer für Skalar-Dummy-Argumente vom Typ INTEGER, LOGICAL, REAL und COMPLEX, die das Attribut VALUE haben. Für diejenigen, die sich verstecken Boolesches Argument (logisch (Art = C_bool), Wert) wird verwendet, um anzuzeigen ob das Argument vorhanden ist.
Ich fand auch diese Diskussion interessant als historischen Kontext.
Vielleicht könnte jemand, der besser informiert ist, Kommentare dazu haben, ob dies eine schlechte Idee ist (abgesehen davon, dass er compilerabhängig ist), aber zumindest im Hinblick auf den Nennwert scheint es eine gute Lösung zu sein.
Beachten Sie, dass dieses Verhalten nicht Teil des Fortran-Standards ist und von der Implementierung eines bestimmten Compilers abhängig ist. Der Beispielcode segmentiert zum Beispiel bei Verwendung von ifort (Version 16.0.2).
Obwohl ich in den meisten Situationen sicherlich nicht dafür eintreten würde (und in einigen Situationen kann es auch nicht sein), kann man manchmal eine Schnittstelle verwenden, um einen einzigen Einstiegspunkt für mehrere Routinen mit verschiedenen erforderlichen Argumente, anstatt ein optionales Argument zu verwenden. Zum Beispiel könnte Ihr Code wie
geschrieben werden %Vor%Auch hier empfehle ich diesen Ansatz nicht, aber ich dachte, ich sollte ihn trotzdem als alternative Möglichkeit hinzufügen, etwas zu liefern, das wie ein Standard aussieht.
Ich hoffe, dass Fortran eine populäre Syntax wie
unterstützt %Vor%oder in einem Fortran-Stil
%Vor%aber das scheint nicht unterstützt (Stand 2016). Einige Umgehungslösungen müssen also von der Benutzerseite durchgeführt werden ...
In meinem Fall habe ich mich nach dem Versuch-und-Irrtum darauf festgelegt, einen Unterstrich an das optionale Dummy-Argument anzuhängen, und mache so etwas wie (*)
%Vor% Andere Leute scheinen das umgekehrte Muster zu mögen (zB Dummy-Variable = & gt; sep
, lokale Variable = & gt; sep_
, siehe teilen () in StringiFor , zum Beispiel) . Wie in dieser Zeile zu sehen, ist dies der kürzeste Weg, um den Standardwert festzulegen ist
Da aber auch diese Zeile etwas ausführlich ist, definiere ich normalerweise ein Makro wie
%Vor%in einer gemeinsamen Header-Datei und verwenden Sie es als
%Vor%Ich glaube jedoch, dass dies noch alles andere als elegant ist und nicht mehr als ein Versuch, es etwas weniger fehleranfällig zu machen (durch Verwendung des gewünschten Variablennamens im Körper der Subroutine).
Eine andere Problemumgehung für eine sehr "große" Subroutine könnte sein, einen abgeleiteten Typ zu übergeben, der alle verbleibenden Schlüsselwortargumente enthält. Zum Beispiel
%Vor%Dies könnte ein bisschen nah an dem sein, was von einigen dynamischen Sprachen unter der Haube gemacht wird, aber das ist in der obigen Form wieder alles andere als elegant ...
(*) 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. Außerdem wäre es wohl leistungsfähiger, Python usw. zu verwenden, um flexiblere Präprozessoren zu erstellen (z. B. PreForM.py und fypp und so weiter, zB um eine Syntax wie subroutine sub( val = -1 )