无点程序组成

时间:2016-07-08 17:31:06

标签: ghostscript postscript

假设我在堆栈上有两个程序p1p2,我想要使用它们并在堆栈上留下一个结合其效果的新程序。我想要一个程序来做到这一点。如果我总是愿意做一些字典簿记,这很容易。但是我可以不引入任何名字吗? (请注意,我想要生成的过程,而不仅仅是在当前堆栈上执行组合效果。)

考虑例如

/compose {<< /f1 4 2 roll /f2 exch >>begin {f1 f2} end}bind def

当然,这不会起作用,因为在end之后f1和f2将是未知的。但是这个破碎的代码应该说明我之后的事情。

1 个答案:

答案 0 :(得分:1)

这完全可能,而且非常困难。您使用每个过程对象后跟可执行文件名exec创建一个新数组。然后使该数组可执行。

/combine { % {a} {b}  .  {{a} exec {b} exec}
    /exec cvx exch     % {a} exec {b}
    /exec cvx          % {a} exec {b} exec
    4 array astore     % [{a} exec {b} exec]
    cvx                % {{a} exec {b} exec}
} def

对于更接近原始样式的样式,使用命名参数,我会这样写:

% fun1 fun2  compose  proc
/compose { 2 dict begin       % f1 f2
    {f2 f1}{exch def} forall  %
    ({ //f1 exec //f2 exec }) % ({ //f1 exec //f2 exec })
    cvx exec                  % { <f1> exec <f2> exec }
end } def

//immediate-name语法非常强大。这里我在字符串中使用代码模板。当字符串被执行cvx exec时,它会根据内容调用扫描程序,然后它会自动load所有标记为前缀为双斜杠//的标记。注释<f1>表示命名变量的内容。就像程序流中的{executable array}没有执行但在栈上产生proc一样,exec包含一个字符串的字符串也会在栈上产生proc。

对于命名参数样式,我使用了postscript的一些特殊规则:不执行可执行数组,因此变量名数组可以写为可执行数组,然后用作数据而不会有任何额外的麻烦。但是通过使用可执行语法,可以在没有/的情况下编写内容 - 名称。因此,我们可以编写较短的[ /f2 /f1 ]。而不是{ f2 f1 }

参数部分也可以考虑其自身的功能。

/argsbegin { % a r g s _ {n a m e s}  .  -
    dup length dict begin
    {exch def} forall  % currentdict:<</n _  /a s  /m g  /e r  /s a>>
} def

/compose { {f2 f1} argsbegin
    ({//f1 exec //f2 exec}) token pop exch pop %another way to invoke the scanner
end } def

或者,实际上以正确的方式放置参数,它可能如下所示。使用forall循环模拟向后for会更加尴尬。

/argsbegin { % a r g s _ {n a m e s}  .  -
    dup length dup dict begin  % a r g s _ {} n
    1 sub -1 0 {  % a r g s _ {} i
        3 2 roll  % a r g s {} i _
        3 copy    % a r g s {} i _ {} i _
        pop       % a r g s {} i _ {} i
        get       % a r g s {} i _ /s
        exch def  % a r g s {} i
        pop       % a r g s {}
    } for         % {}
    pop
} def

/compose { {f1 f2} argsbegin
    ({//f1 exec //f2 exec}) cvx exec
end } def