Kann man dieses Beispiel so umgestalten, dass auch die Laufvariable \i in der Definition vorkommt.

Etwa

\foreach \i in {1,...,#1} {% \expandafter\gdef\expandafter\temp\expandafter{\temp t\i \\}% }%

funktioniert nicht.

alt text

Oder geht das nur mit größeren Maßnahmen wie z.B. etoolbox?

Öffne in Overleaf
\documentclass[margin=2mm]{standalone}
\usepackage{tikz}

\newcommand{\test}[1]{%
  \def\temp{}%
  \foreach \i in {1,...,#1}
    {%
    \expandafter\gdef\expandafter\temp\expandafter{\temp t\i  \\}%
    }%
  \temp}

\begin{document}

IST:
\begin{tabular}{c}
\test{3}
\end{tabular}

SOLL:
\begin{tabular}{c}
t1 \\ t2 \\ t3 \\
\end{tabular}
\end{document}

gefragt 03 Jun '18, 15:52

cis's gravatar image

cis
9.5k93459491
Akzeptiert-Rate: 29%

bearbeitet 03 Jun '18, 15:53


Während Murmeltier's Antwort bereits eine pragmatische Lösung zeigt, sei im folgenden noch ein wenig erklärt, was die Problematik ist und wie man diese möglichst allgemein lösen kann.

Das Problem mit dem gezeigten Code ist, dass zwar die Definition von \temp in der Schleife mit Hilfe von \expandafter bis nach der einmaligen Expansion des vorherigen \temp verzögert wird, aber \i zur Definition nicht mit expandiert wird. Es gibt also Teile der Definition, die unterschiedlich weit expandiert werden sollen. Man könnte das im konkreten Fall durch weitere \expandafter regeln:

Öffne in Overleaf
\documentclass[margin=2mm]{standalone}
\usepackage{tikz}

\newcommand{\test}[1]{%
  \def\temp{}%
  \foreach \i in {1,...,#1}
    {%
    \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\temp\expandafter\expandafter\expandafter{\expandafter\temp \expandafter t\i  \\}%
    }%
  \temp}

\begin{document}

IST:
\begin{tabular}{c}
\test{3}
\end{tabular}

SOLL:
\begin{tabular}{c}
t1 \\ t2 \\ t3 \\
\end{tabular}
\end{document}

Hier wird durch die zusätzlichen \expandafter zuerst \i expandiert, dann \temp t und dann \gdef\temp{. Es wird weiterhin jeweils nur eine Stufe der Expansion ausgeführt. Das funktioniert also nur, weil \i hier nach der ersten Stufe bereits vollständig zur jeweiligen Zahl expandiert. Müsste \i vollständig expandiert werden, könnte man (wie in Murmeltiers Antwort) zu \xdef greifen. Dabei ist allerdings von Vorteil, wenn das innere \temp nur einstufig expandiert wird. Um das zu erreichen, kann man zu

Öffne in Overleaf
\documentclass[margin=2mm]{standalone}
\usepackage{tikz}

\newcommand{\test}[1]{%
  \def\temp{}%
  \foreach \i in {1,...,#1}
    {%
    \xdef\temp{\unexpanded\expandafter{\temp t}\i\unexpanded{\\}}%
    }%
  \temp}

\begin{document}

IST:
\begin{tabular}{c}
\test{3}
\end{tabular}

SOLL:
\begin{tabular}{c}
t1 \\ t2 \\ t3 \\
\end{tabular}
\end{document}

greifen. \xdef expandiert sein Argument erst vollständig, bevor es dieses für die Definition des Makros (hier \temp) verwendet. Allerdings wird mit Hilfe von \unexpanded\expandafter{\temp dafür gesorgt, dass zuerst \temp wiederum eine Stufe weit expandiert wird (also quasi zu seiner eigenen Definition) und dann dieser Teil (und beispielhaft auch das innerhalb des Arguments von \unexpanded folgende t) vor weiterer Expansion geschützt ist. Damit wird verhindert, dass Teile wie \\, die erst bei der Ausführung von \temp aber nicht bei dessen stückweiser Definition expandiert werden dürfen, in späteren Schritten zu früh expandiert werden. Mehr oder weniger dasselbe könnte man mit LaTeX's \protected@xdef zusammen mit \protect erreichen:

Öffne in Overleaf
\documentclass[margin=2mm]{standalone}
\usepackage{tikz}

\makeatletter
\newcommand{\test}[1]{%
  \def\temp{}%
  \foreach \i in {1,...,#1}
    {%
    \protected@xdef\temp{\temp t\i\protect\\}%
    }%
  \temp}
\makeatother

\begin{document}

IST:
\begin{tabular}{c}
\test{3}
\end{tabular}

SOLL:
\begin{tabular}{c}
t1 \\ t2 \\ t3 \\
\end{tabular}
\end{document}

Hier wird das \\ explizit mit \protect vor jeglicher Expansion innerhalb von \protected@xdef (und allen weiteren Aufrufen davon) geschützt. Die beiden Definitionen sind nicht vollkommen identisch. Das \protect verbleibt bei Verwendung von \protected@xdef nämlich in der Definition, spielt aber normalerweise keine Rolle, weil \protect außerhalb von \protected@…-Befehlen \relax ist.

Besser wäre übrigens, \begin{tabular}{…} und \end{tabular} mit in die Definition von \temp zu stecken. Anderenfalls wird \test nämlich innerhalb der ersten Spalte der Tabelle ausgeführt. Im Beispiel funktioniert das, das muss aber nicht immer so sein. Ich würde also eher etwas wie:

Öffne in Overleaf
\documentclass[margin=2mm]{standalone}
\usepackage{tikz}

\newcommand{\test}[1]{%
  \def\temp{\begin{tabular}{c}}%
  \foreach \i in {1,...,#1}
    {%
      \xdef\temp{\unexpanded\expandafter{\temp t}\i\unexpanded{\\}}%
    }%
  \expandafter\def\expandafter\temp\expandafter{\temp\end{tabular}}%
  \temp}

\begin{document}
IST: \test{3}

SOLL:
\begin{tabular}{c}
t1 \\ t2 \\ t3 \\
\end{tabular}
\end{document}

vorschlagen.

Wenn Du sehen willst, was Stück für Stück innerhalb von \test passiert, kannst du übrigens mit \show\temp am Ende jedes Schleifendurchlaufs dessen aktuelle Definition in die log-Datei schreiben lassen, also beispielsweise:

Öffne in Overleaf
\documentclass[margin=2mm]{standalone}
\usepackage{tikz}

\newcommand{\test}[1]{%
  \def\temp{\begin{tabular}{c}}%
  \show\temp
  \foreach \i in {1,...,#1}
    {%
      \xdef\temp{\unexpanded\expandafter{\temp t}\i\unexpanded{\\}}%
      \show\temp
    }%
  \expandafter\def\expandafter\temp\expandafter{\temp\end{tabular}}%
  \show\temp
  \temp}

\begin{document}
IST: \test{3}

SOLL:
\begin{tabular}{c}
t1 \\ t2 \\ t3 \\
\end{tabular}
\end{document}

verwenden, um in der log-Datei die Information:

Öffne in Overleaf
> \temp=macro:
->\begin {tabular}{c}.
\test ...f \temp {\begin {tabular}{c}}\show \temp 
                                                  \foreach \i in {1,...,#1} ...
l.17 IST: \test{3}

> \temp=macro:
->\begin {tabular}{c}t1\\.
\pgffor@body ...t}\i \unexpanded {\\}}\show \temp

l.17 IST: \test{3}

> \temp=macro:
->\begin {tabular}{c}t1\\t2\\.
\pgffor@body ...t}\i \unexpanded {\\}}\show \temp

l.17 IST: \test{3}

> \temp=macro:
->\begin {tabular}{c}t1\\t2\\t3\\.
\pgffor@body ...t}\i \unexpanded {\\}}\show \temp

l.17 IST: \test{3}

> \temp=macro:
->\begin {tabular}{c}t1\\t2\\t3\\\end {tabular}.
\test ...dafter {\temp \end {tabular}}\show \temp 
                                                  \temp 
l.17 IST: \test{3}

zu erhalten. Achtung: Im Online-Editor Overleaf funktioniert das so nicht, da \show zum einen zu einem Error-Code am Ende des LaTeX-Laufs führt und Overleaf den errorstopmode von TeX verwendet, bei dem nach dem ersten Fehler (und damit nach dem ersten \show) ein Abbruch erfolgt. Einige andere Editoren reagieren eventuell ähnlich.

Permanenter link

beantwortet 04 Jun '18, 09:10

saputello's gravatar image

saputello
11.1k174365
Akzeptiert-Rate: 51%

Danke für die ausführliche Abhandlung.

(05 Jun '18, 22:54) cis
Öffne in Overleaf
\documentclass[margin=2mm]{standalone}
\usepackage{tikz}

\newcommand{\test}[1]{%
  \xdef\temp{}%
  \foreach \i in {1,...,#1}
    {%
    \xdef\temp{\temp t\i \cr}%
    }%
  \temp}

\begin{document}

IST:
\begin{tabular}{c}
\test{3}
\end{tabular}

SOLL:
\begin{tabular}{c}
t1 \\ t2 \\ t3 \\
\end{tabular}
\end{document}

alt text

Permanenter link

beantwortet 03 Jun '18, 21:12

Community's gravatar image

Community
21
Akzeptiert-Rate: 56%

bearbeitet 03 Jun '18, 22:53

Gel%C3%B6scht's gravatar image

Gelöscht
(ausgesetzt)

1

Hinweis: Das funktioniert so natürlich nur, solange wirklich komplett expandiert werden soll! In LaTeX ist es meist besser, \protected@xdef statt \xdef zu verwenden. Dann kann man beispielsweise auch \protect\\ verwenden, wenn man das nicht zur Definitionszeit (sondern erst bei der abschließenden Ausführung von \temp) zu expandierende \\ im Code haben will.

(04 Jun '18, 08:31) saputello

Meine obligatorische Lua-Lösung darf natürlich nicht fehlen. :)

Öffne in Overleaf
\documentclass{article}
\usepackage{tikz}

\newcommand{\test}[1]{%
  \directlua{
    for i = 1,#1 do
        tex.sprint("t" .. i .. [[\noexpand\\]])
    end
  }%
}

\begin{document}

IST:
\begin{tabular}{c}
\test{3}
\end{tabular}

SOLL:
\begin{tabular}{c}
t1 \\ t2 \\ t3 \\
\end{tabular}
\end{document}
Permanenter link

beantwortet 05 Jun '18, 12:05

Henri's gravatar image

Henri
15.7k133943
Akzeptiert-Rate: 46%

bearbeitet 05 Jun '18, 12:05

Deine Antwort
Vorschau umschalten

Folgen dieser Frage

Per E-Mail:

Wenn sie sich anmelden, kommen Sie für alle Updates hier in Frage

Per RSS:

Antworten

Antworten und Kommentare

Markdown-Grundlagen

  • *kursiv* oder _kursiv_
  • **Fett** oder __Fett__
  • Link:[Text](http://url.com/ "Titel")
  • Bild?![alt Text](/path/img.jpg "Titel")
  • nummerierte Liste: 1. Foo 2. Bar
  • zum Hinzufügen ein Zeilenumbruchs fügen Sie einfach zwei Leerzeichen an die Stelle an der die neue Linie sein soll.
  • grundlegende HTML-Tags werden ebenfalls unterstützt

Frage-Themen:

×5

gestellte Frage: 03 Jun '18, 15:52

Frage wurde gesehen: 7,128 Mal

zuletzt geändert: 05 Jun '18, 22:54