2014-03-13 36 views
2

Thinking in Postscript(PDF),第5章,练习3(64-65页),要求读者重构这个代码不存储任何字典条目:LOCAL在Postscript中做了什么?

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语言参考中定义的,在PostScript语言教程和食谱
记录在案第三版
  • 在PostScript中,什么是LOCAL

  • 回答

    3

    没有定义。该代码有点鬼鬼祟祟,因为代码dup 0 4字典把def将采取可执行文件并替换LOCAL与4字典的结果。可执行块({}之间的东西)被复制主要是因为put不返回任何内容。自同一块参考您与

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

    遗留下来的这一切都是有效的,因为当地是从来没有在任何地方使用(这是它的使用之前破坏)。用什么来代替LOCAL并不重要。

    +0

    我不知道一个PS程序是否可以修改可执行数组。这真是鬼鬼祟祟。优秀的答案,谢谢! –

    +0

    嘿,等等。这意味着PostScript就像LISP:_Code只是你执行的数据。如果你愿意,可以操纵。 –

    +1

    @WayneConrad是 – joojaa

    2

    正如joojaa正确解释的那样,LOCAL没有被定义为任何可以正确解释的东西,因为它在执行前被替换。它在构造过程体(数组)时会解析为一个可执行文件的名称,此处的使用仅仅是分配数组中的一个插槽。它实际上可以是任何类型,我经常看到(并写入){ 0 begin ...}出于同样的目的。使用名称可让您为代码的人类阅读者提供更多语义信息。我也看到它在我的矩阵函数中写成{ DICT begin ... }Here,我将它称为STATICDICT,显然。

    对于任何meta-syntactical这样的标记都有一个使用全部大写的惯例。它是一个名称类型的标记,但元语法上,它指的是一个稍后要填入的dicttype对象。没有必要(甚至没有任何机制)宣布您为口译员的利益所做的工作,但通过优先于0可获得更多收益。再一次,因为它将被完全替换,所以你也可以使用字面名/LOCAL来尝试,idunno,解除下一个noob从野鹅追查你的代码寻找LOCAL被定义在哪里?为此,我还写了简单的DUMMY代码待填写。我想这些术语的选择是风格或观众或其他无形质量的问题。叹息......或只是一个背景的问题。

    还有另一种风格适用于在过程体中进行动态替换。通过将字典上的dictstack并将其命名为(内本身,所以这是一个封闭的命名空间),大家可以参考其与//immediate

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

    然后取出词典定义之前。

    end def 
    

    因此限定所述程序通常(在外部级词典(这里未命名的,据推测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在端部当然可以被简化为end def

    一个警告。以这种方式创建的字典是递归地包含在自身中的。不要试图用ghostscript的===操作员来打印它!

    1

    PG的“蓝皮书”的133具有相同的技术的稍微容易例如:

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

    这被修改之前的步骤中定义。缠绕你的头脑比较容易一点。在原文中,对我来说最棘手的部分是“dup”,因为我没有意识到堆栈中的数组并不是一个精确的数组,而是一个数组引用(我正在考虑按值复制,它的功能是copy因此原始代码中的“put”会影​​响带有第一个引用的数组(因此从堆栈中消耗),第二个用于定义过程。这是一个新手的错误,但也许其他新手可以借鉴一下:

    堆栈进展:

    ...            % 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. 
    

    对不起了可能是不正确的符号,我只是盯着这一段时间,而我还不能够节省一些人的凝视时间。请让我知道是否有任何我应该修复的错误或误导性陈述。