我需要编写一个 metapost vardef 来返回几个数值。Metapost 似乎只允许返回一个值。
如何使 metapost vardef 返回多个数值?
答案1
在 MetaPost 中,begingroup ...;... endgroup
构造只能返回单个值,并且会vardef
自动包含其中一个值,但您可以跳出它。如果值是独立的,并且您总是返回相同的数量,则可以使用
vardef returnMultipleValues(expr x) =
x + 1
endgroup, begingroup
x + 2
endgroup, begingroup
x + 3
endgroup, begingroup
x + 4
enddef;
for i := returnMultipleValues(3):
show(i);
endfor;
另一种允许您生成同一组中的值的方法是基于 Sergey Slyusarev 的答案。这里的优点是您不必记住使用scantokens
结果,因为这已经在中处理了vardef
:
vardef returnMultipleValues (expr x) =
save y, s;
string s;
numeric y[];
y1 := x + 1;
y2 := x + 2;
y3 := x + 3;
y4 := x + 4;
s := decimal(y1) & "," & decimal(y2) & "," & decimal(y3) & "," & decimal(y4);
expandafter
endgroup
expandafter gobbled expandafter true scantokens(s) gobble begingroup
enddef;
for i := returnMultipleValues(3):
show(i);
endfor;
编辑:我找到了一种自动化第一个版本并解决分组问题的方法:只需使用
def multireturn(expr first)(text values) =
first for v = values: endgroup, begingroup v endfor
enddef;
vardef returnMultipleValues (expr x) =
save y, s;
numeric y[];
y1 := x + 1;
y2 := x + 2;
y3 := x + 3;
y4 := x + 4;
multireturn(y1,y2,y3,y4)
enddef;
for i := returnMultipleValues(3):
show(i);
endfor;
这是有效的,因为for
一开始就扩展了列表,之后v
是一个胶囊,所以它不再受到组的影响。
答案2
一种方法是将数值转换为字符串,将它们连接起来并返回为单个字符串。然后,您可以使用scantokens
vardef returnMultipleValues (expr x) =
save y;
numeric y[];
y1 := x + 1;
y2 := x + 2;
y3 := x + 3;
y4 := x + 4;
decimal(y1) & "," & decimal(y2) & "," & decimal(y3) & "," & decimal(y4)
enddef;
string something;
something = returnMultipleValues(3);
for i := scantokens(something):
show(i);
endfor;
类似地,你可以使用路径来做同样的事情:
vardef returnMultipleValues (expr x) =
save y;
numeric y[];
y1 := x + 1;
y2 := x + 2;
y3 := x + 3;
y4 := x + 4;
(x, y1) -- (x, y2) -- (x, y3) -- (x, y4)
enddef;
path something;
something = returnMultipleValues(3);
for i := 0 step 1 until length(something):
show(ypart(point i of something));
endfor;
或者,如果您想要返回的值的数量限制为 2 或 3,正如@thruston 所建议的,您可以使用 apair
或 a color
。