Fortran 2003/2008: Elegante Standardargumente?

8

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.

    
kdb 09.06.2016, 10:55
quelle

4 Antworten

4

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.

    
Vladimir F 09.06.2016, 11:26
quelle
6

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:

%Vor%

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).

    
Gabe 19.10.2016 07:04
quelle
1

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.

    
d_1999 09.06.2016 18:39
quelle
1

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

%Vor%

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 )

zu ermöglichen     
roygvib 12.06.2016 19:21
quelle