2014-03-13 59 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. 
    

    對不起了可能是不正確的符號,我只是盯着這一段時間,而我還不能夠節省一些人的凝視時間。請讓我知道是否有任何我應該修復的錯誤或誤導性陳述。