Commands are case insensitive, and have full form, and a shortened abbreviation, often the first letter. Commands have zero or more arguments,depending on the command. This page includes programs written in this terse syntax. M is whitespace-aware. Spaces are treated as a delimiter between commands and arguments. Each command is separated from its arguments by 1 space. Commands with zero arguments are followed by 2 spaces. (technically these are called argumentless commands)
#### Common Commands from all National and International Standards of M
As with all M commands, multiple arguments can be passed to a read command. Constants like quoted strings, numbers, and formatting characters are output directly. Values for both global variables and local variables are retrieved from the user. The terminal waits for the user to enter the first variable before displaying the second prompt.
In addition to local variables, M has persistent, shared variables that are the built-in database of M. They are stored to disk and called _globals_. Global names must start with a __caret__ (__^__).
Any variable (local or global) can be an array with the assignment of a _subscript_. Arrays are sparse and do not have a predefined size. Only if data is stored will a value use memory. Arrays should be visualized like trees, where subscripts are branches and assigned values are leaves. Not all nodes in an array need to have a value.
The index values of Arrays are automatically sorted in order. There is a catchphrase of "MUMPS means never having to say you are sorting". Take advantage of the built-in sorting by setting your value of interest as the last child subscript of an array rather than its value, and then storing an empty string for that node.
A single M file is called a _routine_. Within a given routine, you can break your code up into smaller chunks with _tags_. The tag starts in column 1 and the commands pertaining to that tag are indented.
A tag can accept parameters and return a value, this is a function. A function is called with '$$':
```
; Execute the 'tag' function, which has two parameters, and write the result.
w !,$$tag^routine(a,b)
```
M has an execution stack. When all levels of the stack have returned, the program ends. Levels are added to the stack with _do_ commands and removed with _quit_ commands.
M has an if/else construct for conditional evaluation, but any command can be conditionally executed without an extra if statement using a _postconditional_. This is a condition that occurs immediately after the command, separated with a colon (:).
```jinja
; Conditional using traditional if/else
r "Enter a number: ",num
i num>100 w !,"huge"
e i num>10 w !,"big"
e w !,"small"
; Postconditionals are especially useful in a for loop.
; This is the dominant for loop construct:
; a 'for' statement
; that tests for a 'quit' condition with a postconditional
; then 'do'es an indented block for each iteration
s var=""
f s var=var_"%" q:var="%%%%%%%%%%" d ;Read as "Quit if var equals "%%%%%%%%%%"
. w !,var
;Bonus points - the $L(ength) built-in function makes this even terser
As we saw in the previous example, M has built-in functions called with a single $, compared to user-defined functions called with $$. These functions have shortened abbreviations, like commands.
One of the most useful is __$Order()__ / $O(). When given an array subscript, $O returns the next subscript in that array. When it reaches the last subscript, it returns "".
```jinja
;Let's call back to our ^TEMPS global from earlier:
; A log of temperatures by date and time
s ^TEMPS("11/12","0600",32)=""
s ^TEMPS("11/12","0600",48)=""
s ^TEMPS("11/12","1400",49)=""
s ^TEMPS("11/12","1700",43)=""
; Some more
s ^TEMPS("11/16","0300",27)=""
s ^TEMPS("11/16","1130",32)=""
s ^TEMPS("11/16","1300",47)=""
;Here's a loop to print out all the dates we have temperatures for:
n date,time ; Initialize these variables with ""
; This line reads: forever; set date as the next date in ^TEMPS.
; If date was set to "", it means we're at the end, so quit.
; Do the block below
f s date=$ORDER(^TEMPS(date)) q:date="" d
. w !,date
; Add in times too:
f s date=$ORDER(^TEMPS(date)) q:date="" d
. w !,"Date: ",date
. f s time=$O(^TEMPS(date,time)) q:time="" d
. . w !,"Time: ",time
; Build an index that sorts first by temperature -
; what dates and times had a given temperature?
n date,time,temp
f s date=$ORDER(^TEMPS(date)) q:date="" d
. f s time=$O(^TEMPS(date,time)) q:time="" d
. . f s temp=$O(^TEMPS(date,time,temp)) q:temp="" d
There's lots more to learn about M. A great short tutorial comes from the University of Northern Iowa and Professor Kevin O'Kane's [Introduction to the MUMPS Language][1] presentation. More about M using VistA is at
Intersystems has some products which are a super-set of the M programming language.