For a more comprehensive documentation, a list of examples, and an
exposition of the MGS motivations and background, please visit the
http://mgs.lami.univ-evry.fr. This chapter is only a survival
guide and does not cover the specificities of the MGS
language. Refer to the chapter
Functional for a
presentation of the core concepts of MGS.
MGS is a untyped functionnal language that enables the case-based definition of functions on collections. These functions are called transformation. The language includes also imperatives features like globale variables.
A collection is an aggregate of values structured by topological
relationships. See the chapter
Collections in this documentation
for more details about topological collections. See the chapter
Functional for more details about the notion of transformations.
The top-level read-eval-print loop:
The MGS interpreter reads its input, parses the stream of characters
to recognize an expression, evaluates the expression and prints the
result. To force the end of an expression, one may use the
;; (the double semi-column). In this manual pages, we
often omit the terminator and the examples of expression must be
completed by the
;;. In addition, when using the interpreter on a
standard unix terminal, the input are buffered (by unix) and a final
carriage-return must be entered to complete the input.
The top-level accepts expression and also commands. Commands
are order directed to the interpreter and are not part of the MGS
programming language. Commands always begin with a
!. Type the
at the top level to have a list of the available commands.
identifiers come in simple or quoted form. A quoted
from is a string of characters that begins with a quote
identifiers are predefined variables. The value of a quoted
identifier cannot be changed. A simple identifier is a string of
characters that does not begin with a quote. Simple identifier can
be used by the programmer as the name of a global variable, as the
name of a function parameter or as the name of a variable introduced
by a let.
The quote of a quoted name can often be omitted. Indeed, when a
simple identifier is encountered, the evaluation process looks first
if a value is attached to this identifier. If not, the evaluation
process looks if the corresponding quoted name is defined. So
sin(0.77) is interpreted as
'sin(0.77) until the
sin is defined. When this variable is defined, it is
still possible to access the sin function using the (full) quoted
Global and let variables and their imperative assignation: Some identifiers refer to an imperative variable. Such variables are global to the program or visible only in a scope introduced by a let construct.
:= operator is used to change the value of a global variable:
links the variable identified by
a := 3
ato the value
3until the next affectation. The reference to a global variable that has not been previously affected returns a special value called
<undef>. The evaluation of the expression:
<undef: uninitialized var: an_identifier_not_previously_used >. In contrary to the usual handling of let variables in functional languages, the variables introduced by a let can be assigned in MGS. For example:
is a valid expression that returns
let x = 1 in x:=x+2
3. The same let can be used to introduce several local variables:
The scoping rules are the standard ones: the variable
let x = 1 and y = 2 in x+y
xintroduced by the let is not usable in the expression defining the value of
yare unknown outside the
Function are first-class value that can be given as argument to
another function or returned as the value of a function application.
Functions are defined in a syntax similar to the
usual lambda-calculus. For example,
\x.x defines the identity
function. The application of a function to its argument needs
denotes the application of the identity to the argument 3.
All functions in MGS are curryfied. However, there are some
shortcuts to make the notation more lighter:
can be simplified in
In the same spirit, the application of a function
fto two (or more) arguments can be written
instead of the more heavier
f(2)(3).... Beware that the comma is also the name of an infix operator used to build sequence. For example
1, 2, 3is an expression that builds a sequence of 3 elements. In function application, the comma is interpreted in favor of the application to multiple arguments. To force the application of a function to a sequence build with the comma operator, parenthesis can be used:
denotes the application of function
f(1, 2, 3)
fto three arguments while:
denotes the application of the function
g((1, 2, 3))
gto one argument which is an expression that build a sequence, and
denotes the application of the function
h((1, 2, 3), 4)
hto two arguments (the first is a list and the second is the integer
To give a name to a function, we can use the let construct that binds locally an identifier to a value, or the assignment that changes the value linked to a global imperative variable. For example
let id = \x.x in (id(id))(3)
id(id)is equivalent in the scope of the let, to the expression
(\x.x)(\x.x)which evaluates to the identity function. Outside the
inclause, the identifier
:= operator can used to give a global name to a function:
links the identity function to the identifier
id := \x.x
iduntil the next assignment. There is a short-cut used to define a function and simultaneously to link it to a global identifier:
is equivalent to
fun id(x) = x
The shortcut for the handling of multiple arguments is also provided:
id := \x.x
A function defined with the
fun f(x, y, z) = x + y*z
funconstruct is called a named function by opposition with anonymous function defined using the lambda-notation. There is a special feature linked with the use of
funto define a function: such function can have optional arguments.
Predefined functions, i.e. functions that are "magically" defined
when one enters the MGS top-level, have all a quoted name that
cannot be redefined. For example,
fun 'f(x) = x,
'f := ... or
let 'f = ... are incorrect expressions and are rejected (at the
Some predefined functions have a special infix syntax, like the
+: the syntax
is an alias for the expression
There is another way to define functions:
transformation. Visit the
Functional chapter for a
description of transformations.
Recursion: The name of a named function can be used in the definition of this function. This allows the direct expression of the recursion. For example:
defines the standard factorial function.
fun fact(x) = if x < 1 then 1 else x*fact(x-1) fi
Variable capture and imperative feature:
The partial application of the anonymous function
\x,y.x+y to the
1 returns a function that can be used to compute the
let succ = (\x,y.x+y)(1) in succ(2)
3. It is customary to say that the argument
xthat refers to the value
1is captured in the function
\y.x+yand the result is a cloture, i.e. a function with an environment that binds some variables.
In contrary to the usual handling of let variable in functional languages, in MGS the variable introduced by a let can be assigned. In conjonction with the capture of variables, this features enables intersting behaviors. For example:
is a valid expression. The global variable
f := let x = 1 in \z.x:=x+z
fis linked to a cloture that embeeds the let variable
x. Each time the function
fis called, the store associated to
xis updated. So
f(10)returns the value
11and a consecutive call
Optional arguments of a named function: not yet described
Iteration of the function application: not yet described
Tracing a function: the call to a named function
f can be
traced using the command
!trace f or the expression
(this function takes a string as argument. The command
!untrace f or
untrace("f") can be used to cancel the trace of
f. See the function the definition of the function
trace in the
System chapter. Only named function can be traced, however this
includes predefined functions.
Switch statement: the keyword
switch can be used to avoid a
lot of nested
if ... then ... else ... fi constructions. The use
switch looks very similar as its equivalent construction in C:
case scl_1 : exp_1
case scl_n : exp_n
default : exp_d
compares the evaluation of the expression
exp with each scalar
scli in the order given the user, and returns the evaluation of
the associated expression
exp_i. If no
scl_i matches with
exp_d is evaluated and returned. The
default case is optional ; the returned default value is
<undef: macro: make_switch: switch default case>
exp is evaluated only one time, at the beginning
of the evaluation of the
switch construction. In fact, a
is a syntactic sugar for:
let new_id = exp in
if (new_id == scl_1) then exp_1
else if ...
else if (new_id == scl_n) then exp_n
else exp_d fi ... fi fi
Exception handling: the structures
raise ... and
with ... allows the use of exceptions in MGS. The syntax looks
like the Ocaml one.
To raise an exception, the keywords
raise has to be used as
The exception is identified by an MGS symbol (see the chapter
Scalar for details), here
`symbol. A sequence of arguments can
be associated with these exceptions:
raise (`symbol arg_1, arg_2, ...)
where parentheses can be added around the arguments.
These exceptions can be caught using a
try ... with ... structure :
| `symbol1 (arg1_1, ...) -> exp_1
| `symbol2 (arg2_1, ...) -> exp_2
where the first pipe is optional. If the expression
an exception, the exception value is
matched against the list
`symbol1, `symbol2, .... If the raised
exception corresponds to
exp_i is evaluated where the
arg_1, ... are replaced by the arguments of the
exception. Note the number of arguments has to matched for an
exception to be caught. For example :
raise (`S 1,2,3)
| `S (x,y) -> x*y
| `S (x,y,z) -> x+y+z ;;
The rest of the online-documentation: the on-line documentation is divided in several chapters:
Introis this short introduction to MGS.
Systemdescribes the system-related functions: input/output, process spawning, etc.
Collectionsintroduces the notions of collections in MGS. In this chapter, only the overall structure of the collections types is described, as well as generic functions that can handle any collection types. Each specific type of collection are described in a dedicated chapter.
Scalarcovers the scalar types and the related functions. Scalar type corresponds to indecomposable values. Example of scalar type are integer, boolean or function.
Mathlists the arithmetic operators and the mathematical constants and functions
Functionalintroduces some functional constants and the specification of transformations, which are a special kind of functions that act on collections.
Recorddescribes the record collection type.
Monoidaldescribes the set, multiset and sequence collection types.
GBFdescribes collections defined by a uniform neighborhood. Arrays are a special kind of GBF.
Graphdescribes the graph collection type.
Delaunaydescribes the delaunay collection type.
Chaindescribes the (forthcoming) abstract chain complex collection type.