2016-07-08 35 views
2

假設我有兩個程序p1p2在堆棧上,我想要消耗它們並在堆棧上留下一個組合它們的效果的新程序。我想要一個程序來做到這一點。這很容易,如果我總是願意做一個小字典簿記。但是,我可以做什麼,而不用介紹任何名字? (請注意,我想要得到的程序,而不是僅僅執行當前堆棧上的綜合影響。)點免費程序組成

例如,考慮

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

這當然不是工作,因爲F1和F2將是未知之後end。但是,這個破碎的代碼應該說明我在做什麼。

回答

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 s所有標記以雙斜槓//作爲前綴。註釋<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 

或者,爲了實際上將參數放在正確的位置,它可能如下所示。用for循環來模擬倒退forall只是稍微有些尷尬。

/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 
+0

不錯。我試圖找出一種使用'exec'的方法,但是我沒有意識到我可以在堆棧上推送字面名稱,然後使其可執行。謝謝。 – Alan

+0

你非常歡迎。我喜歡真正進入編程方面的後記問題。在我的[文檔格式引擎](https://github.com/luser-dr00g/ibis.ps/blob/0c0aa7d5bd683d21d9814b2b697a85028bcddc81/ibis.ps#L750)中有一個更復雜的例子,從750到850行定義了一個函數稱爲'addstyle',它執行* morphisms *(變化狀態/恢復狀態函數對)的組合。 –

+0

稍早的同一個程序的草稿是[複習](http://codereview.stackexchange.com/questions/117320/document-formatting-markup-engine-in-postscript),但在GitHub上閱讀更容易行號和語法突出顯示。 –