Archiv verlassen und diese Seite im Standarddesign anzeigen : expandieren von befehlen
Hi Leute!
Gibt es Möglichkeiten vor bzw. nach einem schon vorhandenen Befehl etwas anzufügen, ohne den Namen des Befehls selbst zu ändern oder das originale Makro umzudefinieren?
Ich hab heute eine relativ lange Arbeit mit TeX verfasst und bin im Nachhinein auf ein kleines Problem gestoßen. Da ich relativ viel Mathematik in der Arbeit hab, sind dort auch viele Quantoren vorhanden. Nun ist der Abstand nach (und vor) einem "\exists" etwas zu klein für meinen Geschmack.
Wäre dankbar für jeden Vorschlag.
Micha
Ich hab heute eine relativ lange Arbeit mit TeX verfasst und bin im Nachhinein auf ein kleines Problem gestoßen. Da ich relativ viel Mathematik in der Arbeit hab, sind dort auch viele Quantoren vorhanden. Nun ist der Abstand nach (und vor) einem "\exists" etwas zu klein für meinen Geschmack.
\DeclareMathSymbol{\exists}{\mathbin}{symbols}{"39}
Herbert
Danke für die Antwort! Das funktioniert natürlich, hätte man drauf kommen können ;) Aber wir ist das jetzt: kann ich Befehle irgendwie "verlängern"? Wäre für mein LaTeX-Wissen mal ganz interessant.
Grüße,
Micha
Danke für die Antwort! Das funktioniert natürlich, hätte man drauf kommen können ;) Aber wir ist das jetzt: kann ich Befehle irgendwie "verlängern"? Wäre für mein LaTeX-Wissen mal ganz interessant.
\documentclass[12pt]{article}
\newcommand*\EsIst{Es ist }
\parindent=0pt
\begin{document}
\EsIst
\makeatletter\g@addto@macro{\EsIst}{wie es ist!}\makeatother
\EsIst
\let\EsIstAlt\EsIst
\renewcommand*\EsIst{\EsIstAlt\ und nicht anders!}
\EsIst
\end{document}
Herbert
Stefan_K
01-02-2009, 09:58
Hallo Micha,
siehe vllt. auch Using \expandafter for macro redefinitions (http://texblog.net/latex-archive/plaintex/expandafter/), mit \expandafter kann man das alternativ tun, sogar lokal, während \g@addto@macro global wirkt:
\expandafter\def\expandafter\EsIst\expandafter{\Es Ist wie es ist!}
Wenn man das gruppiert bzw. die Wirkung z.B. durch geschweifte Klammern begrenzt, hat das Makro danach wieder den ursprünglichen Code.
Viele Grüße,
Stefan
siehe vllt. auch Using \expandafter for macro redefinitions (http://texblog.net/latex-archive/plaintex/expandafter/), mit \expandafter kann man das alternativ tun, sogar lokal, während \g@addto@macro global wirkt:
\expandafter\def\expandafter\EsIst\expandafter{\Es Ist wie es ist!}
Wenn man das gruppiert bzw. die Wirkung z.B. durch geschweifte Klammern begrenzt, hat das Makro danach wieder den ursprünglichen Code.
wenn schon, dann richtig:
\expandafter\long\expandafter\def\expandafter\EsIs t\expandafter{\EsIst wie es ist!}
Herbert
Danke euch beiden nochmals.
Die Sache mit expandafter hab ich auch schon gelesen, nur nicht verstanden. Aber implementieren kann man es ja trotzdem. Leider funktioniert das nicht so wirklich. Ich kann doch ein Makro definieren, dass mir das dann vornimmt, oder? ungefähr so:
\newcommand{\commandexp}[2]{\expandafter\def\expandafter#1\expandafter{#1 #2}}
\commandexp{\exists}{\quad}%oder sowas
Dachte ich jedenfalls. Nur funktioniert das leider nicht (speicherüberlauf). Mit
\commandexp{\EsIst}{wie es ist.}
funktionierts aber.
Zweites Problem damit. Wenn ich die Kommando-Expansion mit optionalem Argument definiere
\newcommand{\commandexp}[3][]{\expandafter\def\expandafter#2\expandafter{#1 #2 #3}}
also auch einen Vorsatz erlauben will, funktioniert das überhaupt nicht (Selbst mit dem \long-Zusatz). Warum?
Es juckt mich in den Fingern dieses Problem zu lösen, auch wenns nicht wirklich wichtig ist ;)
Die Sache mit expandafter hab ich auch schon gelesen, nur nicht verstanden. Aber implementieren kann man es ja trotzdem. Leider funktioniert das nicht so wirklich. Ich kann doch ein Makro definieren, dass mir das dann vornimmt, oder? ungefähr so:
du solltest \expandafter ganz schnell vergessen und erst dann wieder darauf zurückkommen, wenn du den ganzen anderen Mechanismus erstmal verstanden
hast. Beispielsweise den Unterschied zwischen \newcommand und \def
Die \expandafter-Orgie ist außerdem nicht immer erfolgreich ...
Es ist besser, du gehst von dem LaTeX-konformen Fall aus:
\documentclass[12pt]{article}
\let\Exists\exists
\renewcommand\exists{\Exists\quad}
\begin{document}
$\exists A$
\end{document}
Herbert
Ok. Dann mach ichs eben so :) Danke für die flotten und informativen Antworten.
Ich werd mich jetzt in die Tiefen der LaTeX-Programmierung begeben und den Unterschied zwischen \def, \let, \relax etc., bzw. zu verstehen versuchen, was dieses \expandafter eigentlich tut. (wäre natürlich auch für jede PM diesbezüglich dankbar ;)).
Bis dann,
Micha
mechanicus
01-02-2009, 13:43
Ok. Dann mach ichs eben so :) Danke für die flotten und informativen Antworten.
Ich werd mich jetzt in die Tiefen der LaTeX-Programmierung begeben und den Unterschied zwischen \def, \let, \relax etc., bzw. zu verstehen versuchen, was dieses \expandafter eigentlich tut. (wäre natürlich auch für jede PM diesbezüglich dankbar ;)).
Bis dann,
Micha
Hallo
im Internet findest du einiges:
http://www.matthiaspospiech.de/blog/2008/04/18/tutorial-zu-expandafter/
Gruß
Marco
Ok. Dann mach ichs eben so :) Danke für die flotten und informativen Antworten.
Ich werd mich jetzt in die Tiefen der LaTeX-Programmierung begeben und den Unterschied zwischen \def, \let, \relax etc., bzw. zu verstehen versuchen, was dieses \expandafter eigentlich tut. (wäre natürlich auch für jede PM diesbezüglich dankbar ;)).
Ich will mir den Befehl \123 definieren, was normalerweise gar nicht geht,
da Ziffern nicht Teil eines Makronames sein können. Es gibt aber
\csname123\endcsname, woraus TeX \123 macht und ausführt. Also könnte man denken,
dass
\newcommand{\csname123\endcsname}{foo}
gehen sollte. Geht aber nicht, weil jetzt der Befehl \newcommand\csname zuerst
bearbeitet wird, was zu einem Fehler führt. Man muss also zuerst
\csname123\endcsname ausführen lassen, _bevor_ \newcommand aktiv wird,
also:
\newcommand\expandafter{\csname123\endcsname}{foo}
Geht aber auch nicht, weil jetzt zuerst \newcommand\expandafter ausgeführt wird,
wieder ein Fehler.
\documentclass[12pt]{article}
\expandafter\newcommand\expandafter{\csname123\end csname}{foo}
\begin{document}
\csname123\endcsname
\end{document}
Jetzt klappt es, weil es von links heißt
\expandafter% führe erst das nach \newcommand aus
\newcommand%
\expandafter% führe erst das nach der Klammer aus
{\csname123\endcsname}{foo}
Dadurch bleibt dann intern \newcommand\123{foo} übrig.
Herbert
Stefan_K
01-02-2009, 18:43
Hallo Herbert,
wenn schon, dann richtig:
\expandafter\long\expandafter\def\expandafter\EsIs t\expandafter{\EsIst wie es ist!}
das sehe ich nicht so. \long ist für ein parameterloses Makro nicht sinnvoll.
Oder was möchtest Du damit erreichen?
Stefan
das sehe ich nicht so. \long ist für ein parameterloses Makro nicht sinnvoll.
Oder was möchtest Du damit erreichen?
Ich verstehe ja, dass du immer deine vielen \expandafter anbringen
willst, aber es funktioniert eben bei jeder Menge an Befehlen nicht!
\expandafter\def\expandafter\exists\expandafter{\e xists\quad}
das war das Ausgangsproblem und auch da geht deine Lösung nicht!
Herbert
Moin moin,
Ich verstehe ja, dass du immer deine vielen \expandafter anbringen
willst, aber es funktioniert eben bei jeder Menge an Befehlen nicht!
ich nicht so ganz, für zumindest einfache Sachen wie bei dem hier vorgestellten \EsIst, genügte da nicht auch so etwas wie
\edef\EsIst{\EsIst\ noch was}
? Ok, bei
\expandafter\def\expandafter\exists\expandafter{\e xists\quad}
das war das Ausgangsproblem und auch da geht deine Lösung nicht!
geht das genauso in die Hose ... aber was macht dann \g@addto@macro hier? Oder hab ich das falsch angewendet?
\documentclass{article}
\makeatletter\g@addto@macro{\exists}{\quad}\makeat other
\begin{document}
$\exists A$
\end{document}
liefert bei mir
! TeX capacity exceeded, sorry [input stack size=5000].
und entsprechend keinen Output -- genauso wie bei der \expandafter-Orgien, selbst mit dieser hier:
\expandafter\long\expandafter\def\expandafter\exis ts\expandafter{\exists\quad}
aber Du sagtest ja bereits
Die \expandafter-Orgie ist außerdem nicht immer erfolgreich ...
Und mit der dort vorgestellten Variante
\let\Exists\exists
\renewcommand\exists{\Exists\quad}
funktioniert es ja auch wunderbar, selbst wenn man \renewcommand* oder gar \def statt \renewcommand hier verwendet: die Redefinition von \exists kommt also durchaus ohne \long aus.;-)
MfG
geht das genauso in die Hose ... aber was macht dann \g@addto@macro hier? Oder hab ich das falsch angewendet?
\documentclass{article}
\makeatletter\g@addto@macro{\exists}{\quad}\makeat other
\begin{document}
$\exists A$
\end{document}
liefert bei mir
! TeX capacity exceeded, sorry [input stack size=5000].
und entsprechend keinen Output -- genauso wie bei der \expandafter-Orgien, selbst mit dieser hier:
\expandafter\long\expandafter\def\expandafter\exis ts\expandafter{\exists\quad}
Die Verfahren \g@addto@macro ist faktisch das gleiche wie die \expandafter.-Orgie,
kann also nur funktionieren, wenn das zu erweiternde Makro selbst erstmal
überhaupt ein Makro ist und dann noch expandierbar. \exists ist kein Makro.
Was es ist, kannst du dir mit \meaning\exists anzeigen lassen. Da keine
Expandierbarkeit vorliegt, kommt es automatisch zu einer Rekursion.
Und mit der dort vorgestellten Variante
funktioniert es ja auch wunderbar, selbst wenn man \renewcommand* oder gar \def statt \renewcommand hier verwendet: die Redefinition von \exists kommt also durchaus ohne \long aus.;-)
Jedes Makro ohne Parameter kommt ohne long aus, es ist nur ein guterStil
\newcommand*
zu nehmen, wenn man kein Argument oder Argumente ohne Absätze hat.
Herbert
Stefan_K
02-02-2009, 19:50
Hallo Herbert,
statt wie in Beitrag #4 und #13 herumzusticheln, könntest Du konstruktiv zeigen, wie man es in solchen Fällen dennoch schaffen könnte, oder auch danach fragen. \expandafter (http://www.tug.org/utilities/plain/cseq.html#expandafter-rp) ist ein ganz simpler Befehl, die Mehrfachanwendung lässt es nur scheinbar komplizierter aussehen.
aber es funktioniert eben bei jeder Menge an Befehlen nicht!
Wie nun schon genannt, funktioniert es nicht bei Befehlen, die nicht expandiert werden. Während \g@addto@macro aus diesem Grund scheitert, kann man die \expandafter-Variante leicht modifizieren, um hierin das Expandieren zu erzwingen.
\expandafter\def\expandafter\exists\expandafter{\e xists\quad}
das war das Ausgangsproblem und auch da geht deine Lösung nicht!
So modifiziert geht sie:
\expandafter\def\expandafter\exists\expandafter{\e xpandafter\mathchar\the\exists\quad}
Die Verfahren \g@addto@macro ist faktisch das gleiche wie die \expandafter.-Orgie
Dass \g@addto@macro jedoch global wirkt, also über die Grenzen einer Umgebung hinaus, ist ein bedeutsamer Unterschied. So definieren manche Klassen (KOMA) und Pakete eine lokale Variante \l@addto@macro, die hier auch genannt werden dürfte.
Rainer, mit \edef kann man es auch so hinkriegen:
\edef\exists{\mathchar\the\exists\quad}
Der \the-Trick samt \expandafter ist natürlich eher was für Interessierte, in der Praxis ist es einfacher, wenn man ein neues Makro definiert und mit \let und \renewcommand arbeitet.
Micha, es freut mich, dass Dich die Hintergründe interessieren. Vielleicht schau einmal in diese Liste: plain TeX books (http://texblog.net/latex-link-archive/plain-tex/). Darunter finde ich das Buch "TeX by Topic" sehr gut zugänglich. Das TeXbuch von Knuth ist natürlich die Referenz und sehr zu empfehlen.
Viele Grüße,
Stefan
So modifiziert geht sie:
\expandafter\def\expandafter\exists\expandafter{\e xpandafter\mathchar\the\exists\quad}
klar ist ja auch viel einfacher als die \let-Variante ... :D
oder
\def\exists{\mathchar"239\quad}
Nichts für ungut ...
Herbert
Danke Herbert und Stefan,
ich hab mal versucht, erst per \meaning herauszufinden, ob ein \mathchar notwendig wäre:
\documentclass[12pt]{article}
\mathchardef\emacromc="0123
\def\emacrosm{short}
\def\foo{foo}
\long\def\foobar{foobar}
\def\firstofndqi#1"#2\null{#1}
\def\firstofndq#1{\expandafter\firstofndqi#1"\null}
\def\firstofnci#1:#2\null{#1}
\def\firstofnc#1{\expandafter\firstofnci#1:\null}
\newcommand*\emacrotmpi{}
\newcommand*\emacrotmpii{}
\newcommand*\emacro[2]{%
\edef\emacrotmpii{\firstofndq{\meaning\emacromc}}%
\edef\emacrotmpi{\firstofndq{\meaning#1}}%
\ifx\emacrotmpi\emacrotmpii
\edef#1{\mathchar\the#1 #2}%
\else
\edef\emacrotmpii{\firstofnc{\meaning\emacrosm}}%
\edef\emacrotmpi{\firstofnc{\meaning#1}}%
\ifx\emacrotmpi\emacrotmpii
\edef#1{#1#2}%
\else
\typeout{Warnung: \string\emacro\ hat sich geweigert, \emacrotmpi\ zu expandieren!}
\fi
\fi
}
\begin{document}
\emacro\exists{\quad}
\emacro\forall{\quad}
\emacro\foo{bar}
\emacro\foobar{blubb}
$\exists A$
$\forall B$
\foo
\foobar
\end{document}
steht natürlich in gar keinem Verhältnis zur \let-Variante :D
aber mir hat's geholfen, (La)TeX wieder ein Stückchen besser zu verstehen.;-)
MfG
ich hab mal versucht, erst per \meaning herauszufinden, ob ein \mathchar notwendig wäre:
steht natürlich in gar keinem Verhältnis zur \let-Variante :D
aber mir hat's geholfen, (La)TeX wieder ein Stückchen besser zu verstehen.;-)
Ja, nur so kapiert man das letztlich.
Deine Idee funktioniert leider nicht immer, da es noch andere Typen
gibt, die ebenfalls keinMakro sind und bei Primitiven klappt die
\expandafter-Orgie sowieso nicht:
\documentclass{article}
\usepackage[T1]{fontenc}
\begin{document}
\makeatletter
\meaning\par
\meaning\@ne
\expandafter\strip@prefix\meaning\pagebreak
\end{document}
Herbert
Moin Herbert,
Danke erstmal für die zusätzlichen Anregungen!
Deine Idee funktioniert leider nicht immer, da es noch andere Typen
gibt, die ebenfalls keinMakro sind und bei Primitiven klappt die
\expandafter-Orgie sowieso nicht:
gerade die Primitiven würde ich gar nicht expandieren wollen; auf ein paar Definitionen muß ich mich auch verlassen können.
\meaning\par
Aha, hier schließt sich der Kreis zum \long.
\meaning\@ne
Das scheint mir so ein Teil nach dem Motto ``damned if you do, damned if you don't'' zu sein: Die Implementation hier im \emacro ließ sich recht einfach analog zum \mathchar realisieren, aber gerade \@ne wird ja nicht nur definiert, sondern bereits verwendet -- und wenn sich hier die Bedeutung ändert, führt es fast unweigerlich zu einem Fehler (wenn auch an anderer Stelle); da fragt man sich, ob die Redefinition eines \mathchar überhaupt so ohne weiteres zulässig ist ... Ich kann ja mal ein paar Warnungen ausgeben lassen;-)
\expandafter\strip@prefix\meaning\pagebreak
Beim Versuch, den String weiter auseinanderzunehmen, bin ich hier sehr schnell an meine Grenzen gestoßen und letztlich bin ich das Problem unter Zuhilfenahme des substr-Pakets umgangen -- aber da kann ich mir später immer noch die Zähne dran ausbeißen;-)
Dabei stellte sich auch noch die Frage, was mit einem Makro passieren soll, das Parameter erwartet und wie man überhaupt an dessen Parameterliste gelangt, wenn dieses Makro auch noch einen optionalen Parameter unterstützt.
Besser erstmal abweisen:
\documentclass[12pt]{article}
\usepackage{substr}
\chardef\emacrotc=`\%
\mathchardef\emacromc="0123
\newcommand*\emacrosm{short}
\newcommand\emacrolm{long}
\makeatletter
\edef\chkstr{\string\@testopt}
\makeatother
\newcommand*\foo{foo}
\newcommand\foobar{foobar}
\newcommand*\baz[1]{baz \textit{#1}}
\newcommand\foobaz[1]{foobaz \textit{#1}}
\long\def\firstofndqi#1"#2\null{#1}
\long\def\firstofndq#1{\expandafter\firstofndqi#1"\null}
\long\def\firstofnci#1:#2\null{#1}
\long\def\firstofnc#1{\expandafter\firstofnci#1:\n ull}
\long\def\firstofngti#1>#2\null{#1}
\long\def\firstofngt#1{\expandafter\firstofngti#1>\null}
\newcommand\emacro[2]{%
\long\edef\emacrotmp{\meaning#1}%
\edef\emacroname{\string#1}%
\long\edef\emacrotmpii{\firstofndq{\meaning\emacro mc}}%
\long\edef\emacrotmpi{\firstofndq{\emacrotmp}}%
\ifx\emacrotmpi\emacrotmpii% Test auf \mathchar
\typeout{Warnung:\string\emacro: `\emacroname' war `\emacrotmpi', wird zu Makro.}%
\edef#1{\mathchar\the#1 #2}%
\else
\long\edef\emacrotmpii{\firstofndq{\meaning\emacro tc}}%
\ifx\emacrotmpi\emacrotmpii% Test auf \char
\typeout{Warnung:\string\emacro: `\emacroname' war `\emacrotmpi', wird zu Makro.}%
\edef#1{\char\the#1 #2}%
\else
\long\edef\emacrotmpiis{\firstofngt{\meaning\emacr osm}}%
\long\edef\emacrotmpis{\firstofngt{\emacrotmp}}%
\long\edef\emacrotmpii{\firstofnc{\emacrotmpiis}}%
\long\edef\emacrotmpi{\firstofnc{\emacrotmpis}}%
\ifx\emacrotmpi\emacrotmpii% Test auf (short) macro
\ifx\emacrotmpis\emacrotmpiis% Test auf nicht optionale Parameter
\IfSubStringInString{\chkstr}{\emacrotmp}{% Test auf \@testopt
\typeout{Fehler: \string\emacro\space mag keine Makros mit optionalen Parametern...(\emacroname)}}{%
\edef#1{#1#2}}%
\else
\typeout{Fehler: \string\emacro: was soll mit Parameter(n) geschehen (\emacroname:\emacrotmp)?}%
\fi
\else
\long\edef\emacrotmpiis{\firstofngt{\meaning\emacr olm}}%
\long\edef\emacrotmpis{\firstofngt{\emacrotmp}}%
\long\edef\emacrotmpii{\firstofnc{\emacrotmpiis}}%
\long\edef\emacrotmpi{\firstofnc{\emacrotmpis}}%
\ifx\emacrotmpi\emacrotmpii% Test auf (long) macro
\ifx\emacrotmpis\emacrotmpiis% Test auf nicht optionale Parameter
\IfSubStringInString{\chkstr}{\emacrotmp}{% Test auf \@testopt
\typeout{Fehler: \string\emacro\space mag keine Makros mit optionalen Parametern...(\emacroname)}}{%
\typeout{Warnung: \string\emacro: \emacroname\space wird zu einem kurzen Makro umdefiniert!}%besitzt eh keine Parameter...
\edef#1{#1#2}}%
\else% langes Makro mit Parameter(n):
\typeout{Fehler: \string\emacro: was soll mit Parameter(n) geschehen (\emacroname:\emacrotmp)?}%
\fi
\else
\typeout{Fehler: \string\emacro\space hat sich geweigert, `\emacroname' zu expandieren!}
\fi
\fi
\fi
\fi
}
\begin{document}
\emacro\exists{\quad}
\emacro\forall{\quad}
\emacro\foo{bar}
\emacro\foobar{blubb}
\emacro\par{\foo}
\emacro\%{\quad\foo}
\emacro\pagebreak{\foo}
\emacro\foobaz{\foo}
\emacro\baz{\foo}
\verb=\exists=: $\exists A$
\verb=\forall=: $\forall B$
\verb=\%=: \%
\verb=\foo=: \foo
\verb=\foobar=: \foobar
\verb=\foobaz{bla}=: \foobaz{bla}
\verb=\baz{bla}=: \baz{bla}
\end{document}
wieder ein Stückchen mehr;-)
MfG
Dabei stellte sich auch noch die Frage, was mit einem Makro passieren soll, das Parameter erwartet und wie man überhaupt an dessen Parameterliste gelangt, wenn dieses Makro auch noch einen optionalen Parameter unterstützt.
Besser erstmal abweisen:
\long\def\firstofndqi#1"#2\null{#1}
\long\def\firstofndq#1{\expandafter\firstofndqi#1"\null}
\long\def\firstofnci#1:#2\null{#1}
\long\def\firstofnc#1{\expandafter\firstofnci#1:\n ull}
\long\def\firstofngti#1>#2\null{#1}
\long\def\firstofngt#1{\expandafter\firstofngti#1>\null}
Hallo Rainer,
statt \null würde ich immer mit
\long\def\firstofndqi#1"#2\@nil{#1}
\long\def\firstofndq#1{\expandafter\firstofndqi#1"\@nil}
...
arbeiten.
Wenn man mal mit TeX angefangen hat, wird das eine Seuche :D
Herbert
Hallo,
ich möchte einen selbsterklärten dreiparametrigen Befehl expandieren:
\newcommand{\stoff}[3]{#3}%nimm nummer 3
soll später wahlweise um folgenden Eigenschaft erweitern:
\subsection{#1}
Meine Versuche mit
\let\Stoff=\stoff
\renewcommand{\stoff}{\Stoff \subsection{#1}}
bzw.
\renewcommand{\stoff}[3]{\Stoff \subsection{#1}}
sind leider gescheitert, da Latex nach dem \renewcommand plötzlich auf das zweite, anstatt des ursprünglich dritten Arguments zugreift.
Stefan_K
31-03-2009, 14:12
Hallo Rafael,
reiche die Parameter weiter, etwa:
\renewcommand{\stoff}[3]{\Stoff{#1}{#2}{#3}\subsection{#1}}
Viele Grüße,
Stefan
Hallo Rafael,
reiche die Parameter weiter, etwa:
\renewcommand{\stoff}[3]{\Stoff{#1}{#2}{#3}\subsection{#1}}
Stefan
Vielen Dank, daran hatte ich schon gedacht, aber mein Hirn sagte mir, dies sei ein Denkfehler. naja, Latex wird mich wohl immer irgendwie stressen.
Grüße
Rafael
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.