MATLAB-Fehler? Fehler "Undefinierte Funktion oder Variable" bei Verwendung desselben Namens für Funktion und Variable

8

Es ist gelegentlich praktisch, eine Funktion als "konstante" Variable in MATLAB zu verwenden. Aber als ich diese Funktion kürzlich nutzte, kam es zu einem unerwarteten Fehler. Wenn ich den MWE unten ausführe, erhalte ich den Fehler Undefined function or variable 'a'. , obwohl die Funktion in der gleichen Datei eindeutig verfügbar ist. Wenn ich die if -Anweisung auskommentiere, verschwindet der Fehler. Dies scheint zu implizieren, dass MATLAB a als eine Variable vorinterpretiert, obwohl die Variable-Zuweisungslinie niemals erreicht wird, wobei die Tatsache ignoriert wird, dass es eine Funktion mit dem gleichen Namen gibt. Ist das ein MATLAB-Bug oder ist es irgendwie das gewünschte Verhalten?

Hier ist das MWE:

%Vor%

Nachverfolgung:

Ich weiß, dass es merkwürdig erscheint, absichtlich den gleichen Namen für eine Variable und eine Funktion zu verwenden, also werde ich ein Beispiel geben, wo dies nützlich sein kann. Zum Beispiel möchten Sie vielleicht eine Funktion verwenden, um eine Konstante zu speichern (wie einen Dateipfad), möchten aber auch einen anderen Wert verwenden können, falls die Funktion nicht gefunden werden kann. So ein Fall könnte aussehen:

%Vor%

Ich weiß, dass Sprachdesign-Entscheidungen oft schwierig und kompliziert sind, aber eine der unglücklicheren Konsequenzen von MATLABs Wahl, die Funktion mit dem gleichen Namen zu ignorieren, ist, dass sie die Kompatibilität zwischen Funktionen und Skripten / Befehlszeile verletzt. Zum Beispiel läuft das Folgende ohne Problem in einem Skript:

%Vor%

wo die Funktion a (oben gezeigt) in einer eigenen Datei gespeichert wird.

    
tarheels 26.05.2016, 23:22
quelle

2 Antworten

9

Es hat damit zu tun, wie Matlab zur Kompilierungszeit eine Namensbindung durchführt. Weil matlabBugTest eine Zeile hat, die a einen Wert zuweist, wird a als Variable bestimmt und die spätere Zeile mit a ist eine Referenz auf diese Variable und kein Aufruf der lokalen Funktion. Modernere Versionen von Matlab, wie meine R2015a installieren, gibt eine klarere Fehlermeldung:

  

Bei der Kompilierung wurde "a" als Variable ermittelt und diese Variable ist nicht initialisiert. "a" ist auch ein Funktionsname und frühere Versionen von MATLAB hätten das aufgerufen   Funktion. MATLAB 7 verbietet jedoch die Verwendung desselben Namens im selben Kontext wie eine Funktion und eine Variable.

Es ist nicht so sehr ein Fehler, denn es ist eine Mehrdeutigkeit, die durch das Benennungsschema eingeführt wurde, das eine Standardauflösungsmethode erhielt, was ärgerlich sein kann, wenn Sie das Problem noch nie zuvor gesehen haben und m-Lint es nicht markiert. Ähnliches Verhalten tritt auf, wenn Variablen in den Arbeitsbereich verschoben werden ohne vorherige Initialisierung.

Die Lösung besteht also darin, entweder den Namen der Funktion oder die Variable in verschiedene Dinge zu ändern, was meiner Meinung nach sowieso gute Praxis ist.

Bei der Betrachtung Ihres Follow-up-Beispiels habe ich ein interessantes Verhalten beim Bewegen von Dingen in der Funktion bemerkt. Erstens, wenn die Funktion entweder extern oder verschachtelt ist, wird das Verhalten sehr gut diskutiert von Suevers Antwort . Wenn die Funktion jedoch lokal ist, können Sie die Einschränkung umgehen (zumindest können Sie in meinen R2014b und R2015a installieren), indem Sie die Funktion aufrufen, bevor Sie sie in eine Variable konvertieren, solange Sie sie initialisieren oder explizit in eine Variable konvertieren irgendwann. Wenn Sie die Fälle durchgehen, werden die folgenden Körper von matlabBugTest folgendermaßen ausgeführt:

  • schlägt fehl:

    %Vor%
  • Läuft:

    %Vor%
  • Läuft:

    %Vor%

Ich bin mir nicht ganz sicher, warum dieses Verhalten so ist, aber anscheinend behandelt der Parser die Dinge anders, abhängig vom Umfang der Funktion und der Reihenfolge der Symbole und in welchen Kontexten.

Wenn Sie also davon ausgehen, dass sich dieses Verhalten nicht geändert hat und auch nicht ändern wird, könnten Sie Folgendes versuchen:

%Vor%

Obwohl, ganz persönliche Meinung hier, würde ich etwas tun wie

%Vor%

Was das Brechen der "Kompatibilität zwischen Funktionen und Skripten / Befehlszeile" angeht, sehe ich das nicht wirklich als ein Problem, da dies zwei völlig unterschiedliche Kontexte sind, wenn es um Matlab geht. Sie können eine benannte Funktion weder in der Befehlszeile noch in einer Skriptdatei definieren. daher gibt es keine Belastung für den Matlab-JIT, um richtig und eindeutig zu bestimmen, ob ein Symbol ein Funktionsaufruf oder eine Variable ist, da jede Zeile sequentiell ausgeführt und nicht kompiliert wird (abgesehen von bestimmten Codeblöcken, die der JIT erkennen und optimieren soll) Schleifen in Skripten). Nun, warum das obige Jonglieren von Deklarationen funktioniert, bin ich nicht ganz sicher, da es auf dem Matlab-JIT beruht, von dem ich nichts weiß (noch habe ich eine Compiler-Klasse genommen, so dass ich nicht einmal einen akademischen Grund bilden könnte) wollte).

    
TroyHaskin 26.05.2016, 23:37
quelle
1

Der Grund, warum Sie dieses Verhalten erhalten, ist wahrscheinlich, dass Matlab die Bereichsauflösung für keine ihrer Anweisungen implementiert hat. Betrachten Sie den folgenden Code,

(a)

%Vor%

Dies würde tatsächlich "foo" anzeigen. Auf der anderen Seite würde,

(b)

%Vor%

gibt Ihnen den Fehler Nicht definierte Funktion oder Variable "a" . Betrachten wir das folgende Beispiel,

(c, 1)

%Vor%

(c, 2)

%Vor%

TroyHaskin gibt in seiner Antwort

Folgendes eindeutig an
  

Es hat damit zu tun, wie Matlab zur Kompilierungszeit eine Namensbindung durchführt. Da matlabBugTest eine Zeile hat, die a einen Wert zuweist, wird a als Variable festgelegt, und die spätere Zeile mit a ist eine Referenz auf diese Variable und kein Aufruf der lokalen Funktion

Matlab unterstützt keine konstanten Ausdrücke und nur eine begrenzte Anzahl von statischen Code-Analysen. Wenn die if-Anweisung das Argument false übernimmt oder wenn enterStatement den Wert false hat, gibt Matlab eine Warnung aus, Diese Anweisung (und möglicherweise folgende) kann nicht erreicht werden . Wenn enterStatement auf "false" gesetzt ist, erzeugt Matlab auch eine andere Warnung, Variable a wird verwendet, aber möglicherweise nicht gesetzt . Wenn jedoch enterStatement = mod(0,2) , also% code_% eine Funktion aufruft, erhalten Sie keine Warnung. Dies bedeutet, dass wenn das Beispiel in der Frage erlaubt war, dann würde (c, 2) kompilieren basierend auf wie die Funktion ausgewertet wurde und das ist ein Widerspruch. Dies würde bedeuten, dass der Code basierend auf seinen Laufzeit-Ergebnissen kompiliert werden müsste.

Hinweis: Sicher könnte es gut sein, wenn Matlab einen Fehler erzeugen könnte, wenn enterStatement ein Ausdruck anstelle einer Konstante enterStatement wäre, aber ob dies möglich ist, hängt davon ab auf die Umsetzung, denke ich.

    
patrik 30.05.2016 07:17
quelle

Tags und Links