Meine letzten beiden Fragen konnten gelöst werden. Allerdings gibt es jetzt wieder Probleme bei Labels und Referenzen darauf. Diese konnte ich mit den bisherigen Lösungen nicht beheben. Deshalb meine Frage, ob es eine grundsätzliche Verfahrensweise gibt, wie man pgfoo-Methoden aufrufen kann, damit sie auch innerhalb von anderen Macros funktionieren? Oder gibt es da einfach kein Allheilmittel und muss von Fall zu Fall unterschiedlich betrachtet werden? Hier mal ein Beispiel, auf das ich jetzt gestoßen bin: Open in writeLaTeX
\documentclass{scrartcl} \usepackage[utf8]{inputenc} \usepackage{pgf} \usepgfmodule{oo} \pgfooclass{MyClass}{ \attribute name; \method MyClass(#1){ % constructor \pgfooset{name}{#1} } \method printName() { \pgfoovalueof{name} } \method getId() {label1} } \pgfoonew \myObject=new MyClass(EinName) \begin{document} \myObject.printName() \section{Section} \label{\myObject.getId()} Lorem \section{Another section} Ipsum \ref{\myObject.getId()}. \end{document} Gibt es eine Lösung das zu beheben? Gibt es eine Möglichkeit derartige Fehler endgültig zu vermeiden? gefragt 06 Aug '14, 16:50 ErnstZ
Ergebnis 5 von 8
show 3 more comments
|
Das objektorientierte Prinzip funktioniert umso besser, je konsequenter man es anwendet. In diesem Fall besteht die Konsequenz darin, nicht das Attribut nach außen zu reichen, sondern eine Methode anzubieten, um auf dem Attribut zu operieren: Open in writeLaTeX
\documentclass{scrartcl} \usepackage[utf8]{inputenc} \usepackage{pgf} \usepgfmodule{oo} \pgfooclass{MyClass}{ \attribute name; \attribute id; \method MyClass(#1){ % constructor \pgfooset{name}{#1}% \pgfooset{id}{\detokenize{#1}}% } \method printName() {% \pgfoovalueof{name}% } \method IdOperation(#1){% \begingroup \pgfooget{id}{\temporaryidvalue}% \edef\temporaryaction{\noexpand\endgroup\noexpand#1{\temporaryidvalue}}% \temporaryaction } } \pgfoonew \myObject=new MyClass(EinName) \begin{document} \myObject.printName() \section{Section} \myObject.IdOperation(\label) Lorem \section{Another section} Ipsum \myObject.IdOperation(\ref). \end{document} Noch konsequenter ist es, nur bestimmte Operationen zuzulassen und für jede einzelne dieser Operationen einzelne Methoden zur Verfügung zu stellen: Open in writeLaTeX
\documentclass{scrartcl} \usepackage[utf8]{inputenc} \usepackage{pgf} \usepgfmodule{oo} \pgfooclass{MyClass}{ \attribute name; \method MyClass(#1){ % constructor \pgfooset{name}{#1}% \pgfooset{label}{\detokenize{#1}}% } \method printName() {% \pgfoovalueof{name}% } \method set label(#1){% \begingroup \pgfoothis.get id(\temporaryidvalue)% \edef\temporaryaction{% \noexpand\endgroup\noexpand\label{objectid.\temporaryidvalue}}% \temporaryaction } \method show reference(){% \begingroup \pgfoothis.get id(\temporaryidvalue)% \edef\temporaryaction{% \noexpand\endgroup\noexpand\ref{objectid.\temporaryidvalue}}% \temporaryaction } \method show page reference(){% \begingroup \pgfoothis.get id(\temporaryidvalue)% \edef\temporaryaction{% \noexpand\endgroup\noexpand\pageref{objectid.\temporaryidvalue}}% \temporaryaction } } \pgfoonew \myObject=new MyClass(EinName) \begin{document} \myObject.printName() \section{Section} \myObject.set label() Lorem \section{Another section} Ipsum \myObject.show reference(). \end{document} Dabei mache ich mir auch gleich zu Nutze, dass Noch schöner wäre, wenn beantwortet 07 Aug '14, 13:25 gast3 Sehr gut Ijon. Gefällt mir richtig gut mit deinem generischen Makro-Dispatch deines ersten Vorschlages. Zur besseren Kontrolle ist dann Variante 2 zu bevorzugen. Ich persönlich nehme jetzt doch das Merge aus beiden und die Verwendung von IdOperation(#1) als Delegatee. Bzgl. privater Methoden kann man das so lösen, dass diese einen möglichst komplizierten Namen bekommen, an den man sich bei vermeintlicher Verwendung nicht erinnern kann ;)
(07 Aug '14, 14:08)
ErnstZ
|
Was Du ja willst, ist ein return wert - und den willst Du geeignet weiter verwenden. Nun gibt es in TeX zwei grundlegend und systematisch verschiedene Konzepte, die tief in der Natur von TeX wurzeln: Expansion und Ausfuehrung. Die genauen Details zu kennen ist notwendig, um das richtig zu verstehen. Wenn Du Dich dafuer interessierst: ich habe zu dem Thema mal auf tex.sx einiges geschrieben, vergleiche https://tex.stackexchange.com/questions/12668/where-do-i-start-latex-programming/27589#27589 . Das diskutiert dieses Thema ausfuehrlich, dann wird auch vieles klarer ueber TeX-Programmierung (und nichts anderes tust Du ja hier). Um in dem Sprech weiterzumachen kann ich nur die Kommentare der anderen wiederholen: In der Konsequenz heisst dass, dass Deine Methoden den gewuenschten Wert in ein Makro schreiben muessen. Das koennte im einfachsten Fall ein fixer Makro-Name der Art Open in writeLaTeX
\documentclass{scrartcl} \usepackage[utf8]{inputenc} \usepackage{pgf} \usepgfmodule{oo} \pgfooclass{MyClass}{ \attribute name; \method MyClass(#1){ % constructor \pgfooset{name}{#1} } \method printName() { \pgfoovalueof{name} } \method getId() {\def\pgfretval{label1}} } \pgfoonew \myObject=new MyClass(EinName) \begin{document} \myObject.printName() \section{Section} \myObject.getId()% \label{\pgfretval} Lorem \section{Another section} \myObject.getId()% Ipsum \ref{\pgfretval}. \end{document} Wie das geaenderte Beispiel zeigt, weist Dieses Idiom ist generall verwendbar und funktioniert meistens bei sowas. Damit kommst Du sicher weiter, was die Nutzung von pgfoo angehet. Ich empfehle Dir die Lektuere des oben genannten Links, falls Du ein "Aha Erlebnis" suchst. beantwortet 06 Aug '14, 22:50 cfeuersaenger cgnieder Danke dir erstmal für die ausführliche Erklärung. Deinen Link werde ich mir auf jeden Fall zu Gemüte führen. Ein Problem mit der Lösung habe ich allerdings noch. Im Sinne der Objektorientierung (OO) gefällt es mir gar nicht, dass eine "globale Variable" (
(07 Aug '14, 09:10)
ErnstZ
Till Thantaus Versuch, OO-Konzepte in LaTeX verfügbar zu machen, ist auf jeden Fall sehr löblich und meinerseits sehr willkommen. Allerdings gibt's da Grenzen die TeX geschuldet sind.
(07 Aug '14, 09:11)
ErnstZ
1
Ich stimme Dir in beiden Kommentaren zu. Eine Alternative, die Till Tantau in seinem Manual selber anspricht, ist: uebergebe den Namen des Ausgabemakros an die Methode. Also sowas wie
(07 Aug '14, 09:49)
cfeuersaenger
Ich habe selbe auch einige Erfahrung mit LaTeX gesammelt - sowohl mit "uebergebe Namen des Ausgabemakros" als auch "weise immer derselben Variable zu" (sowohl global als auch lokal) als auch "expansion vs execute". Meiner Erfahrung nach ist "weise Resultate immer (lokal) derselben Variable wie
(07 Aug '14, 09:50)
cfeuersaenger
Tadaaa, das ist die Lösung :) Das ist dann quasi eine Methode mit Rückgabewert. Somit geht's doch und damit wär ich auch zufrieden.
(07 Aug '14, 09:51)
ErnstZ
1
@Christian: habe mir gerade dein "Notes on Programming in TeX" durchgelesen. Super Einführung! Danke dafür. Mir ist nun Einiges klarer. Definitiv ein Aha-Erlebnis ;)
(07 Aug '14, 12:03)
ErnstZ
Ergebnis 5 von 6
show 1 more comments
|
Das ist das gleiche Problem wie bei Deiner letzten Frage, was man daran merkt, dass die Fehlermeldung die gleiche ist.
korrekt, allerdings bleibt die Fehlermeldung, wenn ich es so versuche zu lösen wie bei meinem letzten Problem
Naja, letztlich willst Du ja, dass das Äquivalent von
\label{label1}
und\ref{label1}
passiert, richtig? Dann solltest Du durch Expansion auch dafür sorgen, dass das, was\label
und\ref
zu sehen bekommen, tatsächlichlabel1
ist und nicht ein Makro, das irgendwann irgendwie dahin kommt.Vielleicht wäre ja etwas wie
\myObject.setReference()
und\myObject.getReference()
, die intern dann\label
und\ref
benutzen, eine Variante für Dich.zu deinem ersten Kommentar: richtig, kann man denn die Expansion irgendwie anstoßen?
zum zweiten Kommentar: sowas ginge, allerdings war meine Idee, einfach nur das Label zurückzugebe, da es unterschiedlich referenziert werden könnte (bspw. pageref) und ich vermeiden wollte, für jede Art der Referenzierung eine Methode zu definieren. Aber das wäre in der Tat eine Möglichkeit.
Grundsätzlich: Wenn etwas in eine Datei geschrieben werden soll (und das ist bei
\label
definitiv der Fall), dann muss das vollständig expandierbar sein! Siehe dazu auch das Themaexpansion
.Mir ist ja nicht so recht klar, wie du mit deiner Methode unterschiedliche Labels erzeugen willst. Abgesehen davon: Wenn ich das richtig sehe, wurde pgfoo entwickelt um komplizierte tikz-Objekte zu "malen". Wenn du das dort verwenden willst, wo expandiert wird, dann musst du die Ausgabe/den "Returnwert" in einem Befehl speichern defreturn{label1) und dann nach Aufruf der Methode label{return} benutzen.
Obiges Beispiel erzeugt natürlich keine unterschiedlichen Labels. Das Beispiel ist nur eine Abstraktion meines eigentlichen Dokuments. Es sollte nur zeigen, was das Problem ist. Ich glaube Minimalbeispiel sagt man dazu ;)