Es ist absolut möglich und nicht sehr schwierig. Sie erstellen ein neues Array mit jedem Prozedurobjekt, gefolgt vom Namen der ausführbaren Datei exec
. Dann mache das Array ausführbar.
/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
Für einen Stil zu Ihrem ursprünglichen näher, mit benannten Argumenten, würde ich es so schreiben:
% 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
Die //immediate-name
Syntax ist sehr mächtig. Hier verwende ich eine Code-Vorlage in einer Zeichenfolge. Wenn der String ausgeführt wird, ruft er den Scanner auf den Inhalt cvx exec
auf und es ist dann, dass es automatisch load
s alle Tokens Präfix mit doppeltem Schrägstrich //
vorangestellt wird. Der Kommentar <f1>
zeigt den Inhalt der benannten Variablen an. Genau wie ein {executable array}
im Programm-Stream nicht ausgeführt wird, sondern den Prozess auf dem Stapel, exec
ing eine Zeichenfolge, die eine enthält, wird auch die proc auf dem Stapel.
Für den benannten Argumentstil verwende ich ein paar spezielle Regeln des Postscript: ausführbare Arrays werden nicht ausgeführt, daher kann das Array von Variablennamen als ausführbares Array geschrieben und dann als Daten ohne zusätzlichen Aufwand verwendet werden. Aber mit der ausführbaren Syntax können die Inhalte - die Namen - ohne die /
s geschrieben werden. Also, anstatt [ /f2 /f1 ]
können wir die kürzere { f2 f1 }
schreiben.
Der Argumentteil könnte auch in seine eigene Funktion einfließen.
/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
Oder, um die Argumente tatsächlich richtig herumzulegen, könnte es wie folgt aussehen. Es ist nur ein wenig peinlicher, eine Rückwärts forall
mit einer for
Schleife zu simulieren.
/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
Schön. Ich habe versucht, einen Weg zu finden, 'exec' zu benutzen, aber ich wusste nicht, dass ich den wörtlichen Namen auf den Stapel schieben und dann ausführbar machen könnte. Vielen Dank. – Alan
Sie sind herzlich willkommen. Ich liebe Postscript-Fragen, die wirklich in die Programmierungsaspekte eingehen. Ich habe ein komplizierteres Beispiel in meinem [Dokumentformatierungsmodul] (https://github.com/luser-dr00g/ibis.ps/blob/0c0aa7d5bd683d21d9814b2b697a85028bcddc81/ibis.ps#L750) von ungefähr Linien 750 bis 850 definiert es eine Funktion namens 'addstyle', die eine Zusammensetzung von * morphisms * (Änderungsstatus/Rücksprungfunktionspaare) ausführt. –
Ein etwas früherer Entwurf des gleichen Programms ist [up for review] (http://codereview.stackexchange.com/questions/117320/document-formatting-markup-engine-in-postscript), aber es ist einfacher, auf GitHub mit zu lesen Zeilennummern und Syntax-Highlighting. –