2016-07-08 18 views
2

Angenommen, ich habe zwei Verfahren p1 und p2 auf dem Stapel, und ich möchte sie verbrauchen und auf dem Stapel ein neues Verfahren, das ihre Effekte kombiniert verlassen. Ich möchte ein Verfahren, um dies zu tun. Das ist leicht genug, wenn ich immer bereit bin, ein wenig Wörterbuchbuchhaltung zu machen. Aber kann ich es tun, ohne irgendwelche Namen einzuführen? (Beachten Sie, dass ich das resultierende Verfahren wollen, nicht nur die kombinierten Auswirkungen auf den aktuellen Stack auszuführen.)Punkt frei Verfahren Zusammensetzung

für Betrachten Beispiel

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

Dies wird natürlich nicht funktionieren, da f1 und f2 unbekannt sein wird nach end. Aber dieser kaputte Code sollte zeigen, wonach ich suche.

Antwort

1

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

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

+0

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

+0

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