METAPOST syntax to set all values of an array at once

The array-like naming convention B[1], E[3] is a MetaPost construction with so-called subscripts (in our case, 1 and 3) rather than real arrays, which MetaPost doesn't handle with. But, as a macro language, you could define your own macro to automatically create pairs (please correct me if I'm using the wrong terminology):

vardef ListofPairs(suffix $)(text Pairs) =
    save i_; i_ := 0; %save makes i_ local
    pair $[]; %define a pair with the variable name $
    %Typical loop over passed elements
    for i = Pairs: $[i_] := i; i_ := i_ + 1; endfor;
enddef;

ListofPairs(B)((5,60),(5,-115),(10,180));

drawdot B[0] withpen pensquare scaled 12 withcolor red;
drawdot B[1] withpen pencircle scaled 10 withcolor green;
drawdot B[2] withpen pencircle scaled 8 withcolor blue;

enter image description here

As a friendly recommendation, don't expect MetaPost to be like "normal" programming languages. Instead, the MetaPost manual is a good starting point (texdoc metapost if you have a complete distribution installed). The METAFONTBook is recommended too, but tbh I didn't read it so far.


This answer is really not much more than a comment on the other one, but the comment box is too small. There are a couple of useful built-in features and macros in plain.mp that help with this sort of task in Metapost.

Consider the following little program:

vardef makePairs@#(text arguments) =
    save i; numeric i; i = -1;
    pair @#[];
    for t = arguments: 
        @#[incr i] = t; 
    endfor;
enddef;

makePairs B ((0,1), (1, 2), (2, 3));

for i=0 upto 9:
    if known B[i]: show i; show B[i]; fi
endfor
end

If you run this with mpost you should get the following output

>> 0
>> (0,1)
>> 1
>> (1,2)
>> 2
>> (2,3)

Notes

  • I've avoided using the trailing _ in my variable names, to avoid any possibility of overwriting something in plain.mp, where _ is used in the names of internal variables

  • I have used the special suffix parameter notation @# instead of a delimited suffix parameter. This allows for a slightly more "natural" syntax; the user can write makePairs B ((0,1),....) instead of makePairs(B)((0,1),...).

  • After save i, I have redeclared i as numeric, so that any previous value is removed. This is just good practice.

  • I have used the macro incr from plain.mp to increment the index instead of the clunky i := i + 1 syntax.

  • Finally I have used known to check whether a particular suffix is defined in my "array". In Metapost, variables with numeric suffixes are quite unlike arrays in other languages, despite appearances. So it is possible to define B[0] and B[2], without defining B[1] and there is no way to check the "length" of suffixed variable.

Further simplification

And if you like the above, note that you can omit the parentheses from the final parameter, so we can make the syntax even less fussy for the user, like this:

vardef declarePairs@# text arguments =
    save i; numeric i; i = -1;
    pair @#[];
    for t = arguments: 
        @#[incr i] = t; 
    endfor;
enddef;

declarePairs B (0,1), (1, 2), (2, 3);

for i=0 upto 9:
    if known B[i]: show i; show B[i]; fi
endfor
end

And yet another idea

Depending on what you want to do with all the pairs in the "array", one other possibility is to create them all as a single path:

path p; 
p = (0,1) .. (1,2) .. (2,3);

then you can get at each pair with point 0 of p, point 1 of p, and so on. You don't actually have to draw the path, you could just use it as a sort-of list structure. And in this case MP does provide a length command and you can reverse it with reversed or do certain simple bits of arithmetic on the whole thing. For example p := p shifted up would add 1 to the ypart of each point in the path.

Tags:

Metapost