如何对带有标签的后缀变量的 vardef 声明进行参数化?

如何对带有标签的后缀变量的 vardef 声明进行参数化?

在 metapost 中,我尝试定义一个宏,为各种相关属性提供声明。

我有一个“对象”(本例中为 xyz),用变量上的后缀来表示,还有该对象的几个属性,用该后缀上的标签来表示.a,,,.b等等.c

我的目标是让我的宏声明这些变量,而不是由调用者声明它们。

我有:

vardef S@#(expr p) =
    pair s@#.a;
    pair s@#.b;
    pair s@#.c;

    s@#.c := p;
    draw s@#.c withpen pencircle scaled 6bp withcolor blue;
enddef;

beginfig(1)
    S.abc(origin);
    S.xyz(origin);
endfig;

end.

abc这对于命名我的“对象”和来说很好xyz,但我希望它们以数字形式命名,就好像它们是一个数组一样,这样我可以写:

S0(origin);
S1(origin);

我不明白为什么这是一个错误,因为据我所知它应该产生一个变量s0.c。但是:

! Illegal suffix of declared variable will be flushed.
<to be read again>
                   1
S->begingroup.pair.s(SUFFIX2)
                             c;

是否有可能做到这一点?

我不会介意稍微改变一下语法,比如n(S0, origin)如果有必要的话。但我正尝试利用 Metapost 的后缀(无论是显式的还是隐式的)与标签结合。

谢谢

答案1

问题是你不能在声明中有明确的下标。

@#扩展为数字标记(例如)时0,您的宏会尝试声明pair s0a;哪个会触发您看到的错误。

Metapost 语法规则仅允许在类型声明中使用“集体”下标。这些下标由空括号表示[],因此,如果要使用数字作为对象,则必须将声明更改为:

pair s[]a;
pair s[]b;
pair s[]c;

但这将仅有的处理数字,这样你就可以拥有

S0(origin);

但不是

S.abc(origin); % <-- won't work  

背景介绍

回顾一下有关 token 的规则可能会有所帮助。Metapost 遵循 Knuth 的 Metafont Book 第 6 章中规定的标记化规则。有三种类型的 token:

  • 数字标记,例如3.14, 42,.866
  • 字符串标记,例如"phvr8r""
  • 象征性标记(其他一切)。

然后将符号标记分为“火花”和“标签”:“火花”是对 MP 有意义的符号标记(原始命令的名称或定义的宏的名称);每个其他符号标记都是一个标签。

当您声明一个新变量时,它的名称必须以标签开头。

这条规则听起来很晦涩,但它只是意味着变量名不能以字符串开头,或以数字标记开头,或以已经用于宏或原始命令的名称开头。这对于编程语言来说很正常。

MP 中变量名的棘手之处在于,您还可以在名称中添加一个称为“后缀”的东西。有效后缀的规则是

  • 空的
  • 或有效后缀后跟标签
  • 或者一个有效的后缀,后跟一个称为“下标”的东西,它是一个简单的数字标记,或者是一个用括号括起来的数值表达式。

这意味着你可以使用像p.as12k43leftt[42]或 这样的变量名f[i+1]。带括号的变量名看起来很像数组,但实际上并非如此。

唯一的限制是带下标的变量必须具有相同的类型。这是由上述规则强制执行的,该规则禁止在类型声明中使用显式下标,但允许使用“集体”下标。

可能的解决方案

如果您想要找到一种完全通用的方式来声明相关属性,那么您可以重用generic_declare标准boxes.mp文件中的例程,该文件将位于您的本地 texmf 树中。

相关内容