2016-07-08 4 views
2

スタックに2つの手順p1p2があるとします。それらを消費し、それらの効果を組み合わせた新しい手順をスタックに残したいとします。私はこれを行う手順が欲しいです。私はいつも少し辞書の簿記をしたいと思うなら、これは簡単です。しかし、私はそれを何も名前を導入せずに行うことはできますか? (現在のスタック上の複合効果を実行するだけでなく、私は結果の手続きをしたいことに注意してください。)ポイントフリー手順の構成

F1、F2は不明となりますので、これは当然のことながら動作しません

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

例えば考えてみましょう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のすべてのトークンの先頭に二重スラッシュ//が付加されます。コメント<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というループでシミュレートするのはちょっと面倒です。

/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行目まで、関数を定義するより複雑な例があります* morphisms *(状態の状態の変化と状態の復元)の合成を行う、「addstyle」と呼ばれるものです。 –

+0

同じプログラムのわずかに早い草案が[レビュー用]です(http://codereview.stackexchange.com/questions/117320/document-formatting-markup-engine-in-postscript)が、GitHubで読むのは簡単です行番号と構文ハイライト –