METAPOST 语法用于一次性设置数组的所有值

METAPOST 语法用于一次性设置数组的所有值

我想将 METAPOST 数组的所有值设置到一行中,就像在其他编程语言中编写的那样。

在我能找到的所有示例或手册示例中,人们都单独定义数组元素,如果数组很长,我会觉得非常繁琐:

pair B[];
B1 :=(5,60);
B2 := ...
etc...

除其他外,我尝试了以下方法,但都产生错误:

B[] := ((5,60),(5,-115),(10,180));
B := (5,60),(5,-115),(10,180);
B := [(5,60),(5,-115),(10,180)];
....

有没有综合方法来设置大数组的值?我找不到任何参考资料,在 metapost 中甚至可能都不可能?

答案1

类似数组的命名约定是 MetaPost 的构造B[1]E[3]具有所谓的下标(在我们的例子中是13),而不是真正的数组,MetaPost 无法处理。但是,作为宏语言,您可以定义自己的宏来自动创建对(如果我使用了错误的术语,请纠正我):

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;

在此处输入图片描述

友情建议,不要指望 MetaPost 像“普通”编程语言。相反,MetaPost 手册是一个很好的起点(texdoc metapost如果您安装了完整的发行版)。METAFONTBook也推荐,但说实话我还没读过。

答案2

这个答案实际上只不过是对另一个答案的评论,但评论框太小了。Metapost 中有几个有用的内置功能和宏可以plain.mp帮助完成此类任务。

考虑下面的小程序:

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

如果你运行它,mpost你应该得到以下输出

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

笔记

  • _我避免在变量名中使用尾随,以避免在 中覆盖某些内容的可能性plain.mp,其中_在内部变量的名称中使用

  • 我使用了特殊的后缀参数符号@#来代替分隔suffix参数。这允许使用稍微更“自然”的语法;用户可以这样写makePairs B ((0,1),....)而不是makePairs(B)((0,1),...)

  • 之后save i,我将其重新声明i为数字,这样任何先前的值都会被删除。这只是一个好习惯。

  • 我使用宏incrplain.mp增加索引,而不是使用笨重的i := i + 1语法。

  • 最后,我使用 来known检查我的“数组”中是否定义了特定的后缀。在 Metapost 中,带有数字后缀的变量与其他语言中的数组完全不同,尽管外观如此。因此,可以定义B[0]B[2],而无需定义B[1],并且无法检查后缀变量的“长度”。

进一步简化

如果您喜欢上述内容,请注意您可以从最后一个参数中省略括号,这样我们可以让语法对用户来说更加简单,如下所示:

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

还有另一个想法

根据您想要对“数组”中的所有对执行的操作,另一种可能性是将它们全部创建为一个path

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

然后你可以得到每一对point 0 of ppoint 1 of p您实际上不必绘制路径,您可以将其用作某种列表结构。在本例中,MP提供一个length命令,然后您可以将其反转reversed或对整个过程进行某些简单的算术运算。例如,p := p shifted upypart路径中每个点的加 1。

相关内容