metapost vardef 返回多个值

metapost vardef 返回多个值

我需要编写一个 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

相关内容