Warum passiert das?
Bill Gould hat einen sehr nützlichen Artikel dazu geschrieben, der Mata Matters: Macros genannt wird. Ich empfehle, das Ganze zu lesen, aber ich stelle fest, dass ein wichtiger Teil darin besteht, dass Makros in Stata und Mata unterschiedlich expandiert sind.
In Stata, der Wert eines Makro in einer for-Schleife kann mit jeder Iteration der Schleife ändern:
forvalues i = 1/100 {
* The for-loop has only one line of code and one macro,
* but the macro expands to 100 different values over
* the course of the loop.
display `i'
}
jedoch in Mata, ein Makro erweitert wird nur einmal — wenn die Mata Funktion oder Anweisung wird kompiliert. Wenn die Funktion erneut ausgeführt wird, wird das Makro nicht erneut erweitert, auch wenn sich sein Wert geändert hat.
Mit anderen Worten, erste der Mata-Code kompiliert wird, bei der alle Makros sofort erweitert werden genau einmal, dann der kompilierte Code ausgeführt wird. Es spielt keine Rolle, ob der ausgeführte Code die Werte der Makros ändert, da die Makros in diesem Mata-Code nie wieder erweitert werden.
Im Fall Ihrer for-Schleife ist es so, als ob Mata die Schleife nach irgendwelchen Makros durchsucht, sie durch ihre Werte ersetzt und erst dann die for-Schleife ausführt. Der resultierende Code ist derselbe wie wenn Sie die for-Schleife nur mit den Werten der Makros geschrieben hätten, ohne dass sie tatsächlich Makros hätten.
Dies bedeutet, dass, da Sie das erste if
in einer For-Schleife gewickelt haben, die darin enthaltenen Makros sofort erweitert werden, bevor die Schleife ausgeführt wird. Ihr if
Block enthält die folgenden Zeilen:
st_local("j_ll",strofreal(j))
st_local("filenumber_ll",filenumber)
stata(`" display "Filenumber=`filenumber_ll'" "')
stata(`" display "J=`j_ll'" "')
Wenn `j_ll'
und `filenumber'
nicht gesetzt ist, wenn die for-Schleife zuerst kompiliert wird, werden sie sofort weg erweitert.Es ist genau das gleiche, als wenn Sie eingegeben hatte:
st_local("j_ll",strofreal(j))
st_local("filenumber_ll",filenumber)
stata(`" display "Filenumber=" "')
stata(`" display "J=" "')
Erst wenn die Makros werden erweitert und die for-Schleife kompiliert ist die Schleifendurchlauf.
Wenn das keinen Sinn ergibt, geht Bill Gould in dem Artikel mehr in die Tiefe.
Was bedeutet das für Ihren Code?
Sie noch ein Makro des Änderungswert in Mata zugreifen können, kann man einfach nicht die `localname'
Syntax verwenden, dies zu tun. Verwenden Sie stattdessen st_local()
. Ihre letzten beiden Zeilen würde:
stata(`" display "Filenumber="' + st_local("filenumber_ll") + `"" "')
stata(`" display "J="' + st_local("j_ll") + `"" "')
Wenn Sie eine einzelne Makros Änderungswert oder den Wert eines Makro-Reihe nach dem Mata-Code für den Zugriff kompiliert, verwenden st_local()
. `localname'
ist normalerweise für den Zugriff auf den unveränderlichen Wert eines Makrosatzes reserviert, bevor der Mata-Code kompiliert wird.
Jetzt sind diese beiden Zeilen nicht gerade der weltweit lesbarste Code. Zur Vereinfachung, benutzen Sie einfach die Mata-Variablen, die bereits vorhanden sind:
stata(`" display "Filenumber="' + filenumber + `"" "')
stata(`" display "J="' + strofreal(j) + `"" "')
Besser noch, ersetzen stata(`"display ..."')
mit der Mata display()
Funktion:
display("Filenumber=" + filenumber)
display("J=" + strofreal(j))
Ähnlich fopen()
verwenden und die anderen Mata Dateifunktionen statt stata(`"file ..."')
. Oder, anstatt eine Datei zu verwenden, speichern Sie einfach die Werte, die Sie in Mata-Variablen benötigen, die Sie am Ende des Codes anzeigen, oder verwenden Sie _error()
, um einen Fehler auszulösen und den Code sofort zu stoppen.
Warum hat es interaktiv funktioniert?
Ihr Code funktioniert interaktiv, weil die interaktiven Aussagen nicht umgebrochen werden in einem if-Block, for-Schleife oder eine Funktion und kompiliert werden dann sofort ausgeführt, einer nach dem anderen. Sie werden nicht auf einmal kompiliert und als Block ausgeführt.
Dies bedeutet, dass die früheren Zeilen, die die Werte der Makros ändern, die späteren Zeilen beeinflussen. Das ist nicht der Fall, wenn die Zeilen zusammen kompiliert werden.
Matt, danke für die sehr detaillierte Antwort. Ich verstehe es jetzt viel besser. Inzwischen legte ich den Inhalt der Schleife innerhalb einer anderen do-Datei und nenne es dann innerhalb der Schleife. In diesem Fall scheinen die Makros mit jeder Iteration aktualisiert zu werden und tun, was ich wollte. Aber deine Lösung ist viel eleganter. Danke nochmal! Ich habe mehrere Tage damit verbracht, es herauszufinden. – Odysseus56