Discussion:
\newcommand mit mehr als 9 Argumenten
(zu alt für eine Antwort)
Frank Knappe
2006-08-28 20:20:16 UTC
Permalink
Hallo!

Ist es moeglich ein newcommand mit mehr als 9 Argumenten zu definieren?

Folgender Versuch

\newcommand*{\designsfourfiguresfull}[11]{%
% 1. max. width of left figure
% 2. Space between boxes
% 3. max. width of right figure
% 4. Name of upper left figure
% 5. Name of upper right figure
% 6. Caption of upper left box
% 7. Caption of upper right box
% 8. Name of lower left figure
% 9. Name of lower right figure
% 10. Caption of lower left box
% 11. Caption of lower right box
\settoheight{\doubleparboxht}{\includegraphics[width=#1]{#4}}%
\settoheight{\@tempdima}{\includegraphics[width=#3]{#5}}%
\ifdim \doubleparboxht >\@tempdima
\setlength{\doubleparboxht}{\@tempdima}%
\fi
\subfigure[#6]{\includegraphics[height=\doubleparboxht]{#4}}%
\hspace{#2}%
\subfigure[#7]{\includegraphics[height=\doubleparboxht]{#5}}\\%
\subfigure[#10]{\includegraphics[height=\doubleparboxht]{#8}}%
\hspace{#2}%
\subfigure[#11]{\includegraphics[height=\doubleparboxht]{#9}}%
}

liefert folgende Fehlermeldung:
! You already have nine parameters.
--
Ciao , Frank.
Philipp Lehman
2006-08-28 21:13:32 UTC
Permalink
Post by Frank Knappe
Ist es moeglich ein newcommand mit mehr als 9 Argumenten zu
definieren?
Nein, aber du kannst kaskadierende Makros verwenden, um die Argumente
in Neunergruppen einzulesen, das geht dann praktisch unbegrenzt.

In diesem Fall würde ich aber ohnehin eher mit keyval.sty arbeiten.
--
Sender address blackholed; do not reply to From: address.
You can still reach me by email at: plehman gmx net.
Ulrich Diez
2006-08-28 22:17:09 UTC
Permalink
Post by Frank Knappe
Ist es moeglich ein newcommand mit mehr als 9 Argumenten zu definieren?
Diese Frage wird in der UK-TeX-FAQ behandelt.
Neulich habe ich in privater e-Mail-Korrespondenz dazu folgendes
geschrieben - man verzeihe mir, dass ich das jetzt nicht ins Deutsche
übersetze, aber bei Interesse bin ich gerne bereit das nachzuholen:
("\hfil\break" ist so 'ne Art Zeilenumbruch, in LaTeX könnte man
statt desssen auch "\newline" verwenden.)

[...]
Post by Frank Knappe
This [...] is related to the "UK List of TeX Frequently Asked
Questions on the Web", Section "Macro programming", question
"How to break the 9-argument limit"
(http://www.tex.ac.uk/cgi-bin/texfaq2html?label=moren9).
1. \blah (re)defines argument-holding macros from arguments and
then calls \BlahRelay which fetches more arguments and
additionally uses the previously (re)defined argument-holding
macros.
2. keyval-package.
Both suggestions do not work for expandable contexts as with both
approaches assigning takes place.
[...]
Post by Frank Knappe
There are at least two more well-known variations on the subject
whereby the first can be used in expandable contexts also
[...]
Post by Frank Knappe
1) Within expandable contexts you probably can work around the
9-argument-restriction by "argument-nesting", that means by
actually passing several parameter-values to one macro-argument
\documentclass{minimal}
\newcommand\firstoftwo[2]{#1}
\newcommand\secondoftwo[2]{#2}
\newcommand\internal[9]{%
\noindent
This is value 1: \firstoftwo#1\hfil\break
This is value 2: \secondoftwo#1\hfil\break
This is value 3: \firstoftwo#2\hfil\break
This is value 4: \secondoftwo#2\hfil\break
This is value 5: \firstoftwo#3\hfil\break
This is value 6: \secondoftwo#3\hfil\break
This is value 7: \firstoftwo#4\hfil\break
This is value 8: \secondoftwo#4\hfil\break
This is value 9: \firstoftwo#5\hfil\break
This is value 10: \secondoftwo#5\hfil\break
This is value 11: \firstoftwo#6\hfil\break
This is value 12: \secondoftwo#6\hfil\break
This is value 13: \firstoftwo#7\hfil\break
This is value 14: \secondoftwo#7\hfil\break
This is value 15: \firstoftwo#8\hfil\break
This is value 16: \secondoftwo#8\hfil\break
This is value 17: \firstoftwo#9\hfil\break
This is value 18: \secondoftwo#9\hfil\break
}
\begin{document}
\internal{{one}{two}}%
{{three}{four}}%
{{five}{six}}%
{{seven}{eight}}%
{{nine}{ten}}%
{{eleven}{twelve}}%
{{thirteen}{fourteen}}%
{{fifteen}{sixteen}}%
{{seventeen}{eighteen}}%
\end{document}
If the unbelievable happens and you need more than 18 arguments,
you can define argument-grabber-macros \firstofnine ...
\ninthofnine.
You can also implement more argument-nesting-levels. Then you
have to call a sequence of argument-grabbers. You can do this
in terms of \expandafter or -perhaps less cumbersome- you
define your argument-grabbers to place another argument in
\documentclass{minimal}
\newcommand\callonfirstoftwo[3]{#1#2}
\newcommand\callonsecondoftwo[3]{#1#3}
\newcommand\internal[2]{%
\noindent
\callonfirstoftwo{\callonfirstoftwo\empty}#1\hfil\break
\callonfirstoftwo{\callonsecondoftwo\empty}#1\hfil\break
\callonsecondoftwo{\callonfirstoftwo\empty}#1\hfil\break
\callonsecondoftwo{\callonsecondoftwo\empty}#1\hfil\break
\callonfirstoftwo{\callonfirstoftwo\empty}#2\hfil\break
\callonfirstoftwo{\callonsecondoftwo\empty}#2\hfil\break
\callonsecondoftwo{\callonfirstoftwo\empty}#2\hfil\break
\callonsecondoftwo{\callonsecondoftwo\empty}#2\hfil\break
}
\begin{document}
\internal{{{one}{two}}{{three}{four}}}%
{{{five}{six}}{{seven}{eight}}}%
\end{document}
2) Define \blah
- to fetch arguments
- to define \innerblah
- to call \innerblah
Within \innerblah you can use both the arguments #1..#9 of
\documentclass{minimal}
\newcommand\blah[9]{%
\begingroup
\let\innerblah\relax
\newcommand\innerblah[9]{%
\noindent
This is value 1: #1\hfil\break
This is value 2: #2\hfil\break
This is value 3: #3\hfil\break
This is value 4: #4\hfil\break
This is value 5: #5\hfil\break
This is value 6: #6\hfil\break
This is value 7: #7\hfil\break
This is value 8: #8\hfil\break
This is value 9: #9\hfil\break
This is value 10: ##1\hfil\break
This is value 11: ##2\hfil\break
This is value 12: ##3\hfil\break
This is value 13: ##4\hfil\break
This is value 14: ##5\hfil\break
This is value 15: ##6\hfil\break
This is value 16: ##7\hfil\break
This is value 17: ##8\hfil\break
This is value 18: ##9\hfil\break
}%
\expandafter\endgroup
\innerblah
}%
\begin{document}
\blah{one}{two}{three}{four}{five}{six}{seven}{eight}{nine}%
{ten}{eleven}{twelve}{thirteen}{fourteen}{fifteen}%
{sixteen}{seventeen}{eighteen}
\end{document}
If the unbelievable happens and you need more than 18
\documentclass{minimal}
\newcommand\blah[9]{%
\begingroup
\let\innerblah\relax
\let\innerinnerblah\relax
\newcommand\innerblah[9]{%
\newcommand\innerinnerblah[2]{%
\noindent
This is value 1: #1\hfil\break
This is value 2: #2\hfil\break
This is value 3: #3\hfil\break
This is value 4: #4\hfil\break
This is value 5: #5\hfil\break
This is value 6: #6\hfil\break
This is value 7: #7\hfil\break
This is value 8: #8\hfil\break
This is value 9: #9\hfil\break
This is value 10: ##1\hfil\break
This is value 11: ##2\hfil\break
This is value 12: ##3\hfil\break
This is value 13: ##4\hfil\break
This is value 14: ##5\hfil\break
This is value 15: ##6\hfil\break
This is value 16: ##7\hfil\break
This is value 17: ##8\hfil\break
This is value 18: ##9\hfil\break
This is value 19: ####1\hfil\break
This is value 20: ####2\hfil\break
}%
\expandafter\endgroup
\innerinnerblah
}%
\innerblah
}%
\begin{document}
\blah{one}{two}{three}{four}{five}{six}{seven}{eight}{nine}%
{ten}{eleven}{twelve}{thirteen}{fourteen}{fifteen}%
{sixteen}{seventeen}{eighteen}{nineteen}{twenty}%
\end{document}
[...]


Ulrich
Ulrike Fischer
2006-08-29 06:58:14 UTC
Permalink
Post by Frank Knappe
Hallo!
Ist es moeglich ein newcommand mit mehr als 9 Argumenten zu definieren?
Im Prinzip ja, durch Schachtelung, aber niemand kann Befehle mit so
vielen Argumenten vernünftig verwenden. Nimm xkeyval.sty.
--
Ulrike Fischer
e-mail: zusätzlich meinen Vornamen vor dem @ einfügen.
e-mail: add my first name between the news and the @.
Ulrich Diez
2006-08-29 08:22:09 UTC
Permalink
Post by Ulrike Fischer
Post by Frank Knappe
Hallo!
Ist es moeglich ein newcommand mit mehr als 9 Argumenten zu definieren?
Im Prinzip ja, durch Schachtelung, aber niemand kann Befehle mit so
vielen Argumenten vernünftig verwenden. Nimm xkeyval.sty.
Für "Benutzermakros" rate ich auch zu (x)keyval.
Aber bei "internals" die nicht für die Benutzerebene gedacht sind,
halte ich es durchaus für vertretbar, auch mal mit 12 Werten zu
arbeiten...

Ulrich
Andreas Matthias
2006-08-29 09:05:29 UTC
Permalink
Post by Ulrich Diez
Post by Ulrike Fischer
Post by Frank Knappe
Ist es moeglich ein newcommand mit mehr als 9 Argumenten zu definieren?
Im Prinzip ja, durch Schachtelung, aber niemand kann Befehle mit so
vielen Argumenten vernünftig verwenden. Nimm xkeyval.sty.
Für "Benutzermakros" rate ich auch zu (x)keyval.
Aber bei "internals" die nicht für die Benutzerebene gedacht sind,
halte ich es durchaus für vertretbar, auch mal mit 12 Werten zu
arbeiten...
Es ist besser eine Aufgabe in kleine Teilaufgaben zu zerlegen, die
so weit wie möglich voneinander entkoppelt sind. Dass sich 12
Parameter überhaupt nicht entkoppeln lassen, ist höchst
unwahrscheinlich.

Ciao
Andreas
Ulrich Diez
2006-08-29 12:12:21 UTC
Permalink
Post by Andreas Matthias
Es ist besser eine Aufgabe in kleine Teilaufgaben zu zerlegen, die
so weit wie möglich voneinander entkoppelt sind. Dass sich 12
Parameter überhaupt nicht entkoppeln lassen, ist höchst
unwahrscheinlich.
Es ist des öfteren so, dass eine Entkoppelung möglich ist, vom
technischen Standpunkt aus aber ineffizienter wird.
(\@firstoftwo und \@secondoftwo sind im LaTeX-Kernel schon
definiert.)

Ulrich
Frank Knappe
2006-08-29 14:08:44 UTC
Permalink
Post by Frank Knappe
Hallo!
Ist es moeglich ein newcommand mit mehr als 9 Argumenten zu definieren?
Stellvertretend fur alle Antworten antworte ich mal auf meine eigene
Frage. Es ist also moeglich, allerdings (zumindest fuer mich in der
aktuellen Situation) nicht trivial und einfach machbar. Gluecklicherweise
ist der Bedarf nach so einer Anordnung von Bildern in meinem Dokument sehr
gering, so dass ein "Hardcoden" von einigen Argumenten moeglich ist. Damit
komme ich dann auf unter 9 Argumente.

Trotzdem danke.
--
Ciao , Frank.
Philipp Lehman
2006-08-29 14:21:46 UTC
Permalink
Post by Frank Knappe
Stellvertretend fur alle Antworten antworte ich mal auf meine eigene
Frage. Es ist also moeglich, allerdings (zumindest fuer mich in der
aktuellen Situation) nicht trivial und einfach machbar.
Es ist eigentlich ganz einfach. Hier mal ein Beispiel, das mit
Dreierblöcken arbeitet:

\newcommand*{\DerBefehl}{%
% bei Bedarf Initialisierung hier
\ParserTeilEins}

\newcommand{\ParserTeilEins}[3]{%
\def\ArgumentA{#1}%
\def\ArgumentB{#2}%
\def\ArgumentC{#3}%
\ParserTeilZwei}

\newcommand{\ParserTeilZwei}[3]{%
\def\ArgumentD{#1}%
\def\ArgumentE{#2}%
\def\ArgumentF{#3}%
\Ausgabe}

\newcommand*{\Ausgabe}{%
1. Argument: \ArgumentA\par
...
6. Argument: \ArgumentF\par}

Wie gesagt: keyval wäre wahrscheinlich besser.
--
Sender address blackholed; do not reply to From: address.
You can still reach me by email at: plehman gmx net.
Ulrich Diez
2006-08-29 17:39:04 UTC
Permalink
Frank Knappe schrieb:

[...]
Post by Frank Knappe
Post by Frank Knappe
Ist es moeglich ein newcommand mit mehr als 9 Argumenten zu definieren?
Stellvertretend fur alle Antworten antworte ich mal auf meine eigene
Frage. Es ist also moeglich, allerdings (zumindest fuer mich in der
aktuellen Situation) nicht trivial und einfach machbar.
Machbar ist es in diesem Fall schon:

Zeile 01: \newcommand*{\designsfourfiguresfull}[11]{%
Zeile 02: % 1. max. width of left figure
Zeile 03: % 2. Space between boxes
Zeile 04: % 3. max. width of right figure
Zeile 05: % 4. Name of upper left figure
Zeile 06: % 5. Name of upper right figure
Zeile 07: % 6. Caption of upper left box
Zeile 08: % 7. Caption of upper right box
Zeile 09: % 8. Name of lower left figure
Zeile 10: % 9. Name of lower right figure
Zeile 11: % 10. Caption of lower left box
Zeile 12: % 11. Caption of lower right box
Zeile 13: \settoheight{\doubleparboxht}{\includegraphics[width=#1]{#4}}%
Zeile 14: \settoheight{\@tempdima}{\includegraphics[width=#3]{#5}}%
Zeile 15: \ifdim \doubleparboxht >\@tempdima
Zeile 16: \setlength{\doubleparboxht}{\@tempdima}%
Zeile 17: \fi
Zeile 18: \subfigure[#6]{\includegraphics[height=\doubleparboxht]{#4}}%
Zeile 19: \hspace{#2}%
Zeile 20: \subfigure[#7]{\includegraphics[height=\doubleparboxht]{#5}}\\%
Zeile 21: \subfigure[#10]{\includegraphics[height=\doubleparboxht]{#8}}%
Zeile 22: \hspace{#2}%
Zeile 23: \subfigure[#11]{\includegraphics[height=\doubleparboxht]{#9}}%
Zeile 24: }

In welchen Zeilen kommen welche Argumente vor?

Zeile 13: #1 #4
Zeile 14: #3 #5
Zeile 18: #6 #4
Zeile 19: #2
Zeile 20: #7 #5
Zeile 21: #10 #8
Zeile 22: #2
Zeile 23: #11 #9

Vertausche Argument 9 und 10 :

Zeile 13: #1 #4
Zeile 14: #3 #5
Zeile 18: #6 #4
Zeile 19: #2
Zeile 20: #7 #5
Zeile 21: #9 #8
Zeile 22: #2
Zeile 23: #11 #10

-> Bis einschl. Zeile 22 brauchst Du 9 Argumente
-> In Zeile 23 brauchst Du zwei Argumente, die Du bisher nicht
gebraucht hast.
=> Wende Schachtelung an und packe die Zeile 23 in ein eigenes
Makro:

\newcommand\innerdesignsfourfiguresfull[2]{%
\subfigure[#2]{\includegraphics[height=\doubleparboxht]{#1}}%
}%

\newcommand*\designsfourfiguresfull[9]{%
% 1. max. width of left figure
% 2. Space between boxes
% 3. max. width of right figure
% 4. Name of upper left figure
% 5. Name of upper right figure
% 6. Caption of upper left box
% 7. Caption of upper right box
% 8. Name of lower left figure
% 9. Caption of lower left box
% 10. Name of lower right figure
% 11. Caption of lower right box
\settoheight\doubleparboxht{\includegraphics[width=#1]{#4}}%
\settoheight\@tempdima{\includegraphics[width=#3]{#5}}%
\ifdim\doubleparboxht>\@tempdima
\setlength\doubleparboxht\@tempdima
\fi
\subfigure[#6]{\includegraphics[height=\doubleparboxht]{#4}}%
\hspace{#2}%
\subfigure[#7]{\includegraphics[height=\doubleparboxht]{#5}}\\
\subfigure[#9]{\includegraphics[height=\doubleparboxht]{#8}}%
\hspace{#2}%
\innerdesignsfourfiguresfull %<-Das holt sich jetzt die restlichen zwei
% Argumente, die noch nicht geholt wurden
% und also noch dastehen.
}

Wenn Du ein konsistentes Schema
"Name-Caption/Name-Caption/Name-Caption/Name-Caption"
haben willst, kannst Du ja auch noch die Argumente 5 und 6
vertauschen.

<OT>

Übrigens: Ein nicht-begrenztes Argument brauchst Du nur in
geschweifte Klammern "{" "}" einzufassen, wenn nicht gewährlei-
stet ist, dass es aus genau einem Token besteht.

Die Tatsache, dass in einer Anleitung für ein Makro bei
Argumenten geschweifte Klammern verwendet werden, bedeutet aber
nicht zwingend, dass alle diese Argumente keine Begrenzer haben.
Man kann laut TeXbook die "left-brace" als "wiederzuverwendenden
Argumentbegrenzer" einsetzen. Dann sollte man sie im folgenden
irgendwo mit einer "right brace" ausbalancieren.
Beim graphics-package wurde das wacker ausgenutzt.

</OT>

Ulrich

Loading...