LOCAL在Postscript中做了什么?

时间:2014-03-13 16:31:46

标签: dictionary postscript

Thinking in Postscript(pdf),第5章,练习3(第64-65页)要求读者重构此代码以不存储任何字典条目:

36 750 moveto /Times-Roman 24 selectfont
% works like “show”, leaving current point at proper location
/ushow
% linethickness lineposition (words) ushow -
{ %def
  LOCAL begin
    /text exch def
    /linepos exch def
    /linethick exch def
    gsave
      0 linepos rmoveto
      text stringwidth rlineto
      linethick setlinewidth stroke
    grestore
    text show
  end
} dup 0 4 dict put def
0.5 -4 (test underlined text) ushow

我的问题是LOCAL。 Ghostscript运行此代码时没有错误,但LOCAL不是:

  • 在练习中定义
  • 在Postcript Language Reference,第三版
  • 中记录
  • 在PostScript语言教程和食谱中记录

在PostScript中,LOCAL是什么?

3 个答案:

答案 0 :(得分:3)

没有任何定义。代码有点偷偷摸摸,因为代码 dup 0 4 dict put def 将采用可执行文件并用 4 dict 的结果替换LOCAL。可复制块({}之间的东西)被复制主要是因为put没有返回任何内容。由于它是对你剩下的同一块的引用

/ushow {-dict- begin ...rest of the executable...} def

这一切都是有效的,因为LOCAL从未在任何地方使用过(它在使用之前就被销毁了)。你使用什么代替LOCAL并不重要。

答案 1 :(得分:2)

正如joojaa正确解释的那样,LOCAL没有被定义为任何好的,因为它在执行之前被替换了。它在构造过程体(数组)期间作为可执行文件名解析,这里它的用途只是在数组中分配一个槽。它实际上可以是任何类型,我经常看到(和写){ 0 begin ...}出于同样的目的。使用名称可以为代码的人类读者提供更多语义信息。我也看到它在我的矩阵函数中写了{ DICT begin ... } Here,我称之为STATICDICT

对于像这样的任何元语法标记,有一种使用所有大写的约定。它是一个名称类型标记,但在元语法上,它指的是稍后要填充的dicttype对象。为了解释者的利益,没有必要(甚至没有任何机制)声明你正在做什么,但是通过DICT优先于0可以获得很多好处。再次,因为它将被完全替换,你也可以使用文字名/LOCAL来尝试,idunno,减轻下一个菜鸟从寻找{{1}的野鹅追逐中读取你的代码} 被定义为??为此,我还简单地为令牌写了LOCAL,以便稍后填写。我认为这些术语的选择是风格或观众或其他无形品质的问题。叹息......或者只是一个背景问题。

还有另一种样式适用于在过程体中进行动态替换。通过将字典放在dictstack上并命名它(在它自身内部,因此它是一个封闭的命名空间),我们可以用DUMMY名称来引用它

//immediate

然后在定义之前删除字典。

4 dict begin
/mydict currentdict def
/proc {
    //mydict begin
    ...
    end
}

因此通常定义过程(在外层词典中(在此未命名,大概是end def )),但是通过名称嵌入了词典,从该名称可用扫描程序体时。

这可以扩展到更多的程序共享相同的私有字典,方法是通过从每个定义的堆栈中提取dict。

userdict

最后的/enddefbegin { currentdict 3 1 roll end def begin } def 4 dict begin /mydict currentdict def /proc1 { //mydict begin ... end } enddefbegin /proc2 { //mydict begin ... end } enddefbegin end 当然可以简化为enddefbegin end

一个警告。以这种方式创建的字典以递归方式包含在自身中。不要尝试使用ghostscript的end def运算符打印它!

答案 2 :(得分:1)

“蓝皮书”第133页有一个相同技术的稍微简单的例子:

/sampleproc 
{ 0 begin 
  /localvariable 6 def 
  end 
} def 
/sampleproc load 0 1 dict put 

此处的过程在修改之前定义。包裹你的想法会更容易一些。在原帖中,对我来说最棘手的部分是“dup”,因为我没有意识到堆栈上的数组不是精确的数组,它是一个数组引用(我想的是按值复制,它的功能是复制-by-reference),因此原始代码中的“put”会影​​响具有第一个引用的数组(因此从堆栈中消耗),第二个引用用于定义过程。这是一个新手的错误,但也许其他新手可以从中学习:

Stack Progression:

...                                               % fast forward
1. ushow --array-- --array-- 0 4 dict | put def   % dict creates a dictionary
2. ushow --array-- --array-- 0 --dict-- | put def % put arrives on stack
3. ushow --array-- --array-- 0 --dict-- put | def % put consumes the array 0 and dict
4. ushow --array-- | def                          % def arrives on stack
5. ushow --array-- def                            % def consumes the remaining tokens
6. 

对于可能不正确的符号表示抱歉,我只是盯着这一段时间,并且认为我可能能够稍微盯着某个人。如果我有任何错误或误导性陈述,请告诉我。