[metapost] accessing variables in nested macros

Piotr Zielinski piotr.zielinski at gmail.com
Fri Feb 9 23:44:16 CET 2007

On 09/02/07, Stephan Hennig <mailing_list at arcor.de> wrote:
> Hi,
> within two macros that share the same initialization calculations I want
> to put those calculations into a new macro called "init".  Now, I don't
> want to pass a whole bunch of variables to "init" and tried a simple def
> declaration in the hope that "init" then shares the context (group and
> variables) of the calling macro.  That is, I expected
> def init=
>  calculation;
> enddef;
> vardef calcA(expr parameters)=
>   init;
> enddef;
> when called, more or less to literally replace "init;" by "calculation;"
> and therefore accessing variables from "calcA" in "init" should be ok.

The problem is that "parameters" is not a variable but a parameter.
These two are very different concepts in Metapost.

Variables, like "b" in your code, are symbols that are replaced by
their values at the time they are accessed.  For example

b := 2; a := begingroup b = 3; b endgroup

ends with a=3 because this is the value of b at the end of the group.
Variables must always be of a specific type.

As opposed to variables, which are expanded "on-demand", parameters are
expanded "in advance".  When metapost encounters "calcA(5)" it
replaces it with its definition (in your case "begingroup init;
endgroup") with all occurrences of "parameters" replaced by "5".  Note
that these substitutions are done when "calcA(5)" is expanded, before
any of its code starts "executing", and are done only within the body
of "calcA".  In particular, at no point there exists a variable called
"parameters", which is why you can't refer to it, and you can't set it
to any value.  If you attempted:

def func(expr t) = t := 5 enddef;

Then a "func(6)" would be expanded to "6 := 5", which doesn't make
sense.  Note that since parameter substitution is purely textual, you
don't have to tell Metapost anything about the type of "parameters"
(as you would have if "parameters" were a variable).

The same applies to a "for" loop in Metapost.  The following code

for i = 1 upto 5: blah i blah  endfor

is textually expanded, and exactly equivalent to

blah 1 blah blah 2 blah blah 3 blah blah 4 blah blah 5 blah

At no point does a variable named "i" exist.

IMHO understanding that, unlike other languages, Metapost does most of
its work by textual substitution is crucial to understand the quirks
(and power) of the language.  Knuth's "MetaFONTbook" is an excellent
source of information.


More information about the metapost mailing list