在PostScript中,定义一个过程来定义其他过程

时间:2017-06-07 05:15:31

标签: postscript

这个问题的目的是从编程角度更好地理解PostScript。下面描述的目标只是用于说明的一个例子。

在PostScript语言中,我可以定义一个过程来设置当前图形颜色,如下所示:

/cRED { 1 0 0 setrgbcolor } def  % define a procedure to set the color to red.

我想知道是否有办法定义一个定义其他颜色程序的程序。假设定义了一个名为cdef的过程。我可以按如下方式使用它:

/cRED 1 0 0 cdef

这应该与之前的cRED定义具有相同的效果。 问题是我似乎无法弄清楚如何在传递给def的过程中“捕获”堆栈上项目的文字值。

我尝试了以下内容:

/cdef { /B exch def /G exch def /R exch def { R G B setrgbcolor } bind def } def
/cRED 1 0 0  cdef
/cGRN 0 1 0  cdef 
/cBLU 0 0 1  cdef

我的期望是,通过使用bindR GB的值将被逐字地捕获。即我期待上面的代码等同于:

/cRED { 1 0 0 setrgbcolor } def
/cGRN { 0 1 0 setrgbcolor } def
/cBLU { 0 0 1 setrgbcolor } def

不幸的是,实际结果是cRED cGRNcBLU都将颜色设置为蓝色。这是因为cRED cGRNcBLU仍然依赖于R GB对象(全局变量)。因此,所有人的颜色都是蓝色,因为cBLU最后定义,设置R GB。显然bind没有按照我的预期工作。

有没有办法定义cdef来实现这个目标?问题的关键是能够从堆栈中弹出一个值并使用def逐字存储它。例如。像这样的伪代码

/cdef { { $ $ $ setrgbcolor } bind def } def

在评估cdef时,将$替换为堆栈顶部项的文字值。因此/cCYN 0 1 1 cdef被评估为/cCYN { 0 1 1 setrgbcolor } bind def

是否有一些运营商符合上述$的目的?运算符pop=index很接近,但似乎不起作用。 此外,立即评估名称(例如//name)的使用似乎很有希望,但它们似乎甚至在执行cdef之前就会被评估。

由于

2 个答案:

答案 0 :(得分:4)

通过"滚动"适当的参数而不是分配它们

/cdef { [ 4 1 roll /setrgbcolor load ] cvx bind def } def

这样,当执行] cvx bind def inside时,它会在操作数堆栈上找到

/YourNameForTheProcedure
[ (i.e. mark)
your three parameters (the mark has been rolled below them)
the setrgbcolor operator (or procedure?)

然后结束]将从三个数字和setrgbcolor中创建一个数组,该数组将由cvx生成一个过程。

注意:然后您必须按正确的顺序传递r,g,b参数:

/CR 1 0 0 cdef
/CG 0 1 0 cdef
/CB 0 0 1 cdef

答案 1 :(得分:4)

斯蒂芬的回答可能是这种情况下最好,最简单的方法。但是还有很多方法可以在后记中构建程序。

由于您知道元素的确切数量,因此您可以跳过与标记混淆的堆栈并按以下方式执行:

/cdef { /setrgbcolor load 4 array astore cvx def } def

更复杂的方法可能对更复杂的功能有用。您可以定义参数并将定义替换为字符串模板。我认为这是你用立即评估的名字努力的方向。执行字符串会产生过程主体,但扫描和评估是在运行时执行的。

/cdef { 
    3 dict begin
        { b g r } { exch def } forall
        ({ //r //g //b setrgbcolor }) cvx exec
    end
    def
} def

另一种方式,这可能是笨拙但非常灵活。

/curry {
    /exec cvx
    3 array astore cvx
} def

/cdef {
    {setrgbcolor} 3{curry}repeat
    def
} def

这导致此过程被定义为值1 2 3:

{ 1 { 2 { 3 { setrgbcolor } exec } exec } exec }

所以,微观效率可能略有下降。但它可以用于各种各样的事情。