Sections
A section-document is an M program that consists of multiple named expressions.
section-document:
section
section:
literal-attributesopt section
section-name ;
section-membersopt
section-name:
identifier
section-members:
section-member section-membersopt
section-member:
literal-attributesopt shared
opt section-member-name =
expression ;
section-member-name:
identifier
In M, a section is an organizational concept that allows related expressions to be named and grouped within a document. Each section has a section-name, which identifies the section and qualifies the names of the section-members declared within the section. A section-member consists of a member-name and an expression. Section member expressions may refer to other section members within the same section directly by member name.
The following example shows a section-document:
section Section1;
A = 1; //1
B = 2; //2
C = A + B; //3
Section member expressions may refer to section members located in other sections by means of a section-access-expression, which qualifies a section member name with the name of the containing section.
section-access-expression:
identifier !
identifier
The following example shows a set of two documents containing sections that are mutually referential:
section Section1;
A = "Hello"; //"Hello"
B = 1 + Section2!A; //3
section Section2;
A = 2; //2
B = Section1!A & " world!"; //"Hello, world"
Section members may optionally be declared as shared
, which omits the requirement to use a section-access-expression when referring to shared members outside of the containing section. Shared members in external sections may be referred to by their unqualified member name so long as no member of the same name is declared in the referring section and no other section has a like-named shared member.
The following example illustrates the behavior of shared members when used across sections within the same set of documents:
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
Defining a shared member with the same name in different sections will produce a valid global environment, however accessing the shared member will raise an error when accessed.
section Section1;
shared A = 1;
section Section2;
shared A = "Hello";
section Section3;
B = A; //Error: shared member A has multiple definitions
The following holds when evaluating a set of section-documents:
Each section-name must be unique in the global environment.
Within a section, each section-member must have a unique section-member-name.
Shared section members with more than one definition raise an error when the shared member is accessed.
The expression component of a section-member must not be evaluated before the section member is accessed.
Errors raised while the expression component of a section-member is evaluated are associated with that section member before propagating outward and then re-raised each time the section member is accessed.
Document Linking
A set of M section documents can be linked into an opaque record value that has one field per shared member of the section documents. If shared members have ambiguous names, an error is raised.
The resulting record value fully closes over the global environment in which the link process was performed. Such records are, therefore, suitable components to compose M documents from other (linked) sets of M documents. There are no opportunities for naming conflicts.
The standard library functions Embedded.Value
can be used to retrieve such "embedded" record values that correspond to reused M components.
Document Introspection
M provides programmatic access to the global environment by means of the #sections
and #shared
keywords.
#sections
The #sections
intrinsic variable returns all sections within the global environment as a record. This record is keyed by section name and each value is a record representation of the corresponding section indexed by section member name.
The following example shows a document consisting of two sections and the record produced by evaluating the #sections
intrinsic variable within the context of that document:
section Section1;
A = 1;
B = 2;
section Section2;
C = "Hello";
D = "world";
#sections
//[
// Section1 = [ A = 1, B = 2],
// Section2 = [ C = "Hello", D = "world" ]
//]
The following holds when evaluating #sections
:
- The
#sections
intrinsic variable preserves the evaluation state of all section member expressions within the document. - The
#sections
intrinsic variable does not force the evaluation of any unevaluated section members.
#shared
The #shared
intrinsic variable returns the contents of the global environment as a record. (The global environment consists of all shared section members as well as any identifiers directly included in the global environment by the expression evaluator.) This record is keyed by identifier name, with each value being the value of the associated identifier.
The following example shows a document with two shared members and the corresponding record produced by evaluating the #shared
intrinsic variable within the context of that document:
section Section1;
shared A = 1;
B = 2;
Section Section2;
C = "Hello";
shared D = "world";
//[
// A = 1,
// D = "world"
//]
The following holds when evaluating #shared
:
The
#shared
intrinsic variable preserves the evaluation state of the global environment.The
#shared
intrinsic variable does not force the evaluation of any unevaluated value.