8
1

In etlichen Codebeispielen findet man den Befehl \relax.

  1. Was macht der genau bzw. welche Aufgaben hat er?
  2. Worin besteht der Unterschied zu {}?

gefragt 24 Jul '13, 09:59

esdd's gravatar image

esdd
17.7k254256
Akzeptiert-Rate: 62%

bearbeitet 24 Jul '13, 10:23

saputello's gravatar image

saputello
11.1k154365


Grundsätzliches

\relax ist ein Token (ein Primitives), das nicht expandierbar ist und nichts macht, wenn es ausgeführt wird. {} sind zwei Token, die (Standard-Kategoriecodes vorausgesetzt) eine leere Gruppe oder nicht begrenztes Argument darstellen.

Eigenschaften

\relax

@saputello hat ja schon geschrieben, dass \relax beim Schreiben mit \write als es selbst geschrieben, also nicht expandierbar ist. \relax (und jede Kontrollsequenz die mit \let äquivalent zu \relax gemacht wurde) bleibt also auch in einem \edef stehen:

Open in writeLaTeX
\edef\foo{\relax}
\show\foo
\bye

zeigt im log

Open in writeLaTeX
> \foo=macro:
->\relax .
l.2 \show\foo

Das kann erwünscht oder unerwünscht sein...

{}

$a+{}$ setzt + als Relation, d.h. mit entsprechend Leerraum herum, da {} ein mathord atom erzeugt. $a+\relax$ wirkt wie $a+$ und setzt + nicht als Relation, d.h. ohne extra Leerraum.

Sowohl {} als auch \relax unterdrücken Ligaturen:

Open in writeLaTeX
Auflauf Auf{}lauf Auf\relax lauf

Allerdings habe ich noch nie gesehen, dass \relax dafür eingesetzt wird. Übrigens funktioniert auch {} dafür nicht zuverlässig. Zum Beispiel werden Ligaturen mit LuaTeX damit nicht unterdrückt.

Anwendungen von \relax

Assignments und \numexpr & \dimexpr

Die Nicht-Expandierbarkeit macht man sich zunutze bei Assignments, die auf der Suche nach ihrem Argument die folgenden Token expandieren bis sie auf etwas Nicht-Expandierbares stoßen:

Open in writeLaTeX
\baselineskip=13pt\relax

In diesen Fällen kann man {} nicht auf gleiche Weise verwenden. Ein Beispiel, wo {} Probleme verursacht, wird gleich gezeigt. Ähnlich verhält es sich mit \ifnum:

Open in writeLaTeX
\ifnum10>\mymacro\relax ...\else ...\fi

\numexpr und \dimexpr sind hier besonders zu erwähnen. Man sollte ihre Ausdrücke immer mit einem \relax beenden, aus einem vergleichbaren Grund wie bei Assignments. \relax wird von ihnen aus dem Input-Stream entfernt, {} würde zurückbleiben. Die Tatsache, dass sie das \relax dann aus dem Imput-Stream entfernen, macht sie verschachtelt verwendbar und trotz des \relax expandierbar_.

Open in writeLaTeX
\the\numexpr(2+3)*4\relax

Ein {} könnte an solchen Stellen durchaus Probleme verursachen, etwa in folgender Definition:

Open in writeLaTeX
\def\mylength{100pt{}}
\hbox to \mylength {bla} % => expandiert zu \hbox to 100pt{}{bla} => wohl nicht gewünscht.

\def\mylength{100pt\relax} hätte in diesem Beispiel wie gewünscht funktioniert.

Einsatz in \write

Man kann sich die Nicht-Expandierbarkeit in einem \write auch zunutze machen, um Befehle in eine Hilfsdatei zu schreiben:

Open in writeLaTeX
{\let\section\relax...\immediate\write\@auxout{... \section}}

Hier wird \section lokal auf \relax gesetzt, wodurch es gefahrlos in die Hilfsdatei geschrieben werden kann. Das gleiche kann man mit {} nicht erreichen.

Namen von Befehlssequenzen

Wenn man \csname foo\endcsname aufruft und das Makro \foo vorher nicht definiert wurde, dann ist es danach äquivalent \relax:

Open in writeLaTeX
\csname foo\endcsname
\show\foo
\bye

gibt im log:

Open in writeLaTeX
> \foo=\relax.
l.2 \show\foo

Auf dieser Tatsache beruht der Test \expandafter\ifx\csname foo\endcsname\relax ob ein Makro definiert ist. Das steht auch hinter der Technik, mit \let\foo\relax das Makro \foo zu „löschen“:

Open in writeLaTeX
\documentclass{article}
\begin{document}
\newcommand\foo{foo}
\let\foo\relax% nun kann \foo mit \newcommand wieder definiert werden
\newcommand\foo{bar}
\end{document}

Die Beispiele habe ich z.T. bei David Carlisle geklaut.

Permanenter link

beantwortet 24 Jul '13, 11:25

cgnieder's gravatar image

cgnieder
22.1k243463
Akzeptiert-Rate: 60%

bearbeitet 29 Jan '14, 21:34

Die Behandlung von \relax bei \numexpr und \dimexpr stellt eine Besonderheit dar, die nicht exemplarisch für andere Behandlungen von \relax ist. Grund dafür ist, dass \numexpr und \dimexpr immer nach einem \relax zur Beendigung des jeweiligen Ausdrucks verlangen. Dass sie das \relax dann entfernen ist notwendig, damit man Ausdrücke ineinander schachtelt kann beispielsweise \dimexpr 12pt*\numexpr 4+3\relax + 14pt\relax. Würde \numexpr das erste \relax nicht entfernen, würde die \dimexpr ebenfalls bei diesem enden.

(24 Jul '13, 12:57) saputello

@Clemens Ich habe mir mal erlaubt, in Deinem Beitrag einen entsprechenden Hinweis direkt bei der Erwähnung von \numexpr einzufügen.

(24 Jul '13, 18:10) saputello

@saputello ich hab die Antwort überarbeitet.

(25 Jul '13, 10:39) cgnieder
1

@saputello müssen impliziert meiner Meinung nach, dass es einen Fehler gäbe, wenn man es weglässt, was aber nicht passiert. \the\numexpr2+3 bla gibt einfach „5bla“

(25 Jul '13, 11:05) cgnieder

@Clemens: Ok, Du hast recht. Ich habe gerade noch einmal in die Syntaxdiagramme von e-TeX geschaut. Ich hatte bei optional spaces and \relax das optional nur auf spaces bezogen. Tatsächlich bezieht es sich aber auf spaces and \relax.

BTW: Der Vollständigkeit halber sei erwähnt, dass es auch noch \muexpr und \glueexpr gibt (was ich bei der Gelegenheit ebenfalls erst entdeckt und noch nie verwendet habe).

(25 Jul '13, 11:10) saputello

@saputello und @Clemens: Vielen Dank für eure ausführliche Antwort.

(26 Jul '13, 21:54) esdd
Ergebnis 5 von 6 show 1 more comments

\relax ist ein TeX-Primitiv, das zu sich selbst expandiert und keine Dokument-Ausgabe erzeugt. Es ist transparent, das bedeutet, es führt – beispielsweise im Unterschied zu einem whatsit – auch nicht zu einer Umschaltung in den horizontalen Modus. Da es sich um eine command sequence handelt, werden Leerzeichen danach ignoriert. Beim Schreiben mit \write wird jede command sequence, die \relax ist, als sie selbst geschrieben.

\let\test\relax
\immediate\write0 {\relax\test}

gibt also \relax\test im Terminal aus.

{} ist (bei den voreingestellten category codes von plainTeX und LaTeX) je nach Kontext ein leeres Argument oder eine leere Gruppe. Im Falle einer leeren Gruppe wird diese bei der Ausgabe allerdings teilweise weg optimiert. Leerzeichen danach sind im horizontalen Modus jedoch signifikant. Beim Schreiben mit \write werden die Klammern mit geschrieben. Als Gruppenklammern expandieren sie ebenfalls immer wieder zu einer leeren Gruppe.

Permanenter link

beantwortet 24 Jul '13, 10:22

saputello's gravatar image

saputello
11.1k154365
Akzeptiert-Rate: 51%

bearbeitet 24 Jul '13, 13:01

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:

×52
×22
×7
×2

gestellte Frage: 24 Jul '13, 09:59

Frage wurde gesehen: 26,883 Mal

zuletzt geändert: 29 Jan '14, 21:34