Abschnitte
Bei einem Abschnittsdokument handelt es sich um ein M-Programm, das aus mehreren benannten Ausdrücken besteht.
section-document:
section
section:
literal-attributesoptsection
section-name;
section-members opt
section-name:
Bezeichner
section-members:
section-member section-membersopt
section-member:
literal-attributesoptshared
section-member-name expression=
;
section-member-name:
identifier
In M ist ein Abschnitt ein organisatorisches Konzept, mit dem verknüpfte Ausdrücke in einem Dokument benannt und gruppiert werden können. Jeder Abschnitt enthält einen Abschnittsnamen, der den Abschnitt identifiziert und die im Abschnitt deklarierten Namen der Abschnittselemente qualifiziert. Ein Abschnittselement besteht aus einem Elementnamen und einem Ausdruck. Abschnittselementausdrücke können je nach Elementnamen direkt auf andere Abschnittselemente innerhalb desselben Abschnitts verweisen.
Das folgende Beispiel zeigt ein Abschnittsdokument:
section Section1;
A = 1; //1
B = 2; //2
C = A + B; //3
Abschnittselementausdrücke können mithilfe eines Abschnittzugriffsausdrucks, der einen Abschnittselementnamen mit dem Namen des enthaltenden Abschnitts qualifiziert, auf Abschnittselemente in anderen Abschnitten verweisen.
section-access-expression:
Bezeichner !
Das folgende Beispiel zeigt einen Satz mit zwei Dokumenten, bei denen sich die enthaltenen Abschnitte gegenseitig referenzieren:
section Section1;
A = "Hello"; //"Hello"
B = 1 + Section2!A; //3
section Section2;
A = 2; //2
B = Section1!A & " world!"; //"Hello, world"
Abschnittselemente können optional als shared
deklariert werden, wodurch die Anforderung, einen Abschnittzugriffsausdruck zu verwenden, beim Verweis auf freigegebene Elemente außerhalb des enthaltenden Abschnitts entfällt. Auf freigegebene Elemente in externen Abschnitten kann von deren nicht qualifizierten Elementnamen verwiesen werden, solange kein Element desselben Namens im verweisenden Abschnitt deklariert wird und kein anderer Abschnitt ein gleichnamiges freigegebenes Element enthält.
Das folgende Beispiel veranschaulicht das Verhalten von freigegebenen Elementen, wenn diese in verschiedenen Abschnitten innerhalb desselben Dokumentsatzes verwendet werden:
section Section1;
shared A = 1; // 1
section Section2;
B = A + 2; // 3 (refers to shared A from Section1)
section Section3;
A = "Hello"; // "Hello"
B = A + " world"; // "Hello world" (refers to local A)
C = Section1!A + 2; // 3
Durch das Definieren eines freigegebenen Elements mit dem gleichen Namen in verschiedenen Abschnitten wird eine gültige globale Umgebung erstellt, allerdings tritt beim Zugriff auf das freigegebene Element ein Fehler auf.
section Section1;
shared A = 1;
section Section2;
shared A = "Hello";
section Section3;
B = A; //Error: shared member A has multiple definitions
Beim Auswerten eines Satzes von Abschnittsdokumenten gilt Folgendes:
Jeder Abschnittsname muss in der globalen Umgebung eindeutig sein.
In einem Abschnitt muss jedes Abschnittsmember über einen eindeutigen Abschnittsmembernamen verfügen.
Freigegebene Abschnittselemente mit mehr als einer Definition lösen einen Fehler aus, wenn auf das freigegebene Element zugegriffen wird.
Die Ausdruckskomponente eines Abschnittselements darf nicht ausgewertet werden, bevor auf das Abschnittselement zugegriffen wird.
Fehler, die während der Auswertung der Ausdruckskomponente eines Abschnittselements ausgelöst werden, werden dem Abschnittselement vor der Weitergabe nach außen zugeordnet und dann jedes Mal wieder ausgelöst, wenn auf das Abschnittselement zugegriffen wird.
Eine Reihe von M-Abschnittsdokumenten kann in einem nicht transparenten Datensatzwert verknüpft werden, der über ein Feld pro freigegebenem Element der Abschnittsdokumente verfügt. Wenn freigegebene Elemente mehrdeutige Namen aufweisen, wird ein Fehler ausgelöst.
Der resultierende Datensatzwert wird vollständig über die globale Umgebung geschlossen, in der der Verknüpfungsprozess ausgeführt wurde. Solche Datensätze sind daher geeignete Komponenten zum Verfassen von M-Dokumenten aus anderen (verknüpften) M-Dokumenten. Es können keine Konflikte im Zusammenhang mit der Benennung auftreten.
Die Standardbibliotheksfunktion Embedded.Value
kann zum Abrufen solcher „eingebetteter“ Datensatzwerte verwendet werden, die wiederverwendeten M-Komponenten entsprechen.
M ermöglicht den programmgesteuerten Zugriff auf die globale Umgebung mithilfe der Schlüsselwörter #sections
und #shared
.
Die intrinsische Variable #sections
gibt alle Abschnitte innerhalb der globalen Umgebung als Datensatz zurück. Dieser Datensatz ist nach Abschnittsnamen geordnet, und jeder Wert ist eine Datensatzdarstellung des entsprechenden Abschnitts, der nach Abschnittselementnamen indiziert ist.
Das folgende Beispiel zeigt das aus zwei Abschnitten bestehende Dokument sowie den Datensatz, der durch Auswerten der intrinsischen Variablen #sections
innerhalb des Kontexts dieses Dokuments erstellt wurde:
section Section1;
A = 1;
B = 2;
section Section2;
C = "Hello";
D = "world";
#sections
//[
// Section1 = [ A = 1, B = 2],
// Section2 = [ C = "Hello", D = "world" ]
//]
Beim Auswerten von #sections
gilt Folgendes:
- Die intrinsische Variable
#sections
behält den Auswertungsstatus aller Abschnittselementausdrücke innerhalb des Dokuments bei. - Die intrinsische Variable
#sections
erzwingt keine Auswertung eines nicht ausgewerteten Abschnittselements.
Die intrinsische Variable #shared
gibt den Inhalt der globalen Umgebung als Datensatz zurück. (Die globale Umgebung besteht aus allen freigegebenen Abschnittsmembern sowie allen Bezeichnern, die direkt durch den Ausdrucksauswerter in die globale Umgebung eingeschlossen sind.) Der Schlüssel für diesen Datensatz ist der Bezeichnername, wobei jeder Wert der Wert des zugeordneten Bezeichners ist.
Das folgende Beispiel zeigt ein Dokument mit zwei freigegebenen Membern sowie den zugehörigen Datensatz, der durch Auswerten der intrinsischen Variable #shared
innerhalb des Kontexts dieses Dokuments erstellt wurde:
section Section1;
shared A = 1;
B = 2;
Section Section2;
C = "Hello";
shared D = "world";
//[
// A = 1,
// D = "world"
//]
Beim Auswerten von #shared
gilt Folgendes:
Die intrinsische Variable
#shared
behält den Auswertungsstatus der globalen Umgebung bei.Die intrinsische Variable
#shared
erzwingt keine Auswertung eines nicht ausgewerteten Werts.