In LaTeX 2ε the arguments of macros and environments either can be optional or can be mandatory.
Mandatory arguments of a macro/of an environment are arguments that have to be provided when calling the macro/the environment. If with a macro-call/an environment-call a mandatory argument is to be empty/is to consist of no token at all or is to consist of more than one token or is to have leading space tokens that would be discarded instead of being tokenized when TeX's reading-apparatus is in state S (skipping blanks) or if it is to have a leading token which otherwise would erroneously mark the begin of an optional argument or the delimiter of a delimited argument, then it needs to be provided nested between a pair of matching curly braces/between a pair of matching explicit character tokens of category 1(begin group) resp. 2(end group). Such braces are stripped off/dropped/thrown away in the course of grabbing the tokens that with the macro-call/environment-call form the argument.
Optional arguments of a macro/of an environment are arguments that, when calling the macro /the environment, can/may be provided but don't have to be provided.
In case with the macro-call/environment-call an optional argument is not provided and thus a value for the corresponding macro's/environment's definition's ⟨replacement text⟩'s placeholder (one of #1
or #2
or #3
or #4
or #5
or #6
or #7
or #8
or #9
) for the tokens that when calling the macro/the environment form the argument is not provided, a default value is used/default tokens are used.
Optional arguments of types O{⟨default⟩}
and o
in macro-calls/environment-calls are to be preceded by a delimiter [12 and themselves are delimited at the right by a delimiter ]12. (12 denotes the category code 12(other).) These delimiters are stripped off/are dropped/are thrown away in the course of grabbing the tokens that form the argument. A pair of matching explicit character tokens of category 1(begin group) resp. 2(end group), usually curly braces {1…}2, surrounding everything that is between [12 and ]12, if present, is stripped off/is dropped/is thrown away also in the course of grabbing the tokens that form the optional argument. This way you can nest optional arguments inside optional arguments without the ]12-delimiter of an innermore optional argument erroneously be taken for the ]12-delimiter of an outermore optional argument.
With an O{⟨default⟩}
-type-argument the user provides the default value/the default tokens at the time of via \NewDocumentCommand
defining the macro/at the time of via \NewDocumentEnvironment
defining the environment.
E.g., with O{\Foo\Bar\Baz}
the default for the optional argument is the token sequence \Foo\Bar\Baz
and with a macro-call/with an environment-call where the optional argument is not provided you get the tokens \Foo\Bar\Baz
for the macro's/environment's definition's ⟨replacement text⟩'s placeholder (one of #1
or #2
or #3
or #4
or #5
or #6
or #7
or #8
or #9
) of that O
-type-argument.
E.g., with O{}
the default for the optional argument is emptiness/is no tokens at all and with a macro-call/with an environment-call where the optional argument is not provided you get emptiness/no tokens for the macro's/environment's definition's ⟨replacement text⟩'s placeholder (one of #1
or #2
or #3
or #4
or #5
or #6
or #7
or #8
or #9
) of that O
-type-argument.
With o
-type-arguments the user does not provide a default at the time of defining the macro/the environment.
An o
-type-argument is like an O{⟨default⟩}
-type-argument where at the time of defining the macro/the environment as ⟨default⟩ a sequence of explicit character tokens is specified which cannot easily be produced via having LaTeX tokenize ordinary user-input, namely the sequence -11, N11, o11, V11, a11, l11, u11, e11, -12. Note that the leading -11 is of category 11(letter) while the trailing -12 is of category 12(other). Let's call that sequence of explicit character tokens the "no-value-marker".
(The tokens forming the no-value-marker are accessible via the expl3 programming layer as the content of a token-list-constant whose name is \c_novalue_tl
. That token list is documented in section "53.2 Constant token lists" of "The LaTeX3 Sources", released 2024-07-20 by The LaTeX Project.)
The tests \IfNoValueT
, \IfNoValueF
and \IfNoValueTF
are to be used for testing whether a sequence of tokens equals that no-value-marker.
These tests are intended to be used with o
-type arguments.
The logic behind this is that with an o
-type-argument in the case of the macro/environment-definition's ⟨replacement text⟩'s placeholder for that o
-type-argument holding only a sequence of tokens which equals the sequence of tokens that makes up the no-value-marker it is assumed that the default is used because no optional argument is provided at all with the macro-call/environment-call.
So these tests are intended for testing whether and forking depending on whether with a call to a macro/to an environment an optional argument of type o
was provided at all. Usually you cannot use an o
-type-argument's default for anything sensible but for doing such testing and forking by means of the \IfNoValueT
/\IfNoValueF
/\IfNoValueTF
-tests. Therefore when writing definitions for macros or environments which process o
-type-arguments it is sort of mandatory to place code into the ⟨replacement-text⟩ for cranking out via \IfNoValueT
/\IfNoValueF
/\IfNoValueTF
whether those arguments hold the default/the no-value-marker or whether those arguments hold something else.
In the last but one paragraph the wording "it is assumed" is used because the test can be fooled by explicitly providing the no-value-marker as optional argument. But that requires some trickery and applying such trickery implies that one is knowing what one is doing and is not doing it accidentally but is doing it deliberately.
In macro-definitions via \NewDocumentCommand
and in environment-definitions via \NewDocumentEnvironment
you use an O{⟨default⟩}
-type-argument when you want TeX to basically behave the same way no matter if an optional argument is or is not explicitly provided with the macro-call/environment-call, in the case of an optional argument not being provided assuming the argument having a default-value/holding the ⟨default⟩-tokens.
In macro-definitions via \NewDocumentCommand
and in environment-definitions via \NewDocumentEnvironment
you use o
-type-arguments and \IfNoValueT
/\IfNoValueF
/\IfNoValueTF
-tests when you want to fork/to implement different behavior depending on whether an optional argument was or was not explicitly provided with the macro-call/environment-call.
The tests \IfBlankT
, \IfBlankF
and \IfBlankTF
are for testing whether it is (not) the case that a sequence of tokens either has no tokens at all or consists only of explicit space tokens. (A so-called explicit space token is an explicit character token of category 10(space) whose character code is 32; the character code 32 denotes the number of the code point of the space character in TeX's internal character representation scheme, which with traditional TeX engines like Donald E. Knuth's TeX and Hàn Thế Thành's pdfTeX is ASCII and with LuaTeX- and XeTeX-engines is unicode.)
You ask why with calling the environment NoticeNV
as in
\begin{NoticeNV}
No Value: These are the times that try men's souls.
\end{NoticeNV}
you get a horizontal space at the left of the first horizontal rule.
Let's look at the definition of the environment NoticeNV
:
\NewDocumentEnvironment{NoticeNV}{O{}}{%
\IfNoValueTF{#1}%
{\noindent\rule{3cm}{1pt} \\}%
{\noindent #1~\rule{3cm}{1pt} \\}%
\noindent{}
}
{
% the following \\ does precede the result of the following test.
\\
\IfNoValueTF{#1}%
{\noindent\rule{3cm}{1pt}}%
{\noindent #1~\rule{3cm}{1pt}}%
}
That environment does process an optional argument whose default is emptiness.
With the call above no optional argument is provided. Thus the default, i.e. emptiness, is used in the place of the environment's ⟨replacement-text⟩'s argument-placeholder #1
.
Thus the test
\IfNoValueTF{#1}%
{\noindent\rule{3cm}{1pt} \\}%
{\noindent #1~\rule{3cm}{1pt} \\}%
, i.e., checking whether #1
consists of those tokens that form the no-value-marker, is applied, while #1
is empty while emptiness in turn is not the same as the special no-value-marker.
Thus TeX ends up doing the F
-branch, which is \noindent #1~\rule{3cm}{1pt} \\
with #1
being empty.
I.e., TeX ends up doing \noindent ~\rule{3cm}{1pt} \\
.
Notice that in your example defining the environment NoticeNV
takes place while LaTeX is not switched to expl3-mode. Therefore ~
denotes a non-break-space.
Now the question is why with the begin of the environment, at the left of the horizontal rule at the top you get that additional indenting of the width denoted by a space token while space factor is 1000 while with the end of the environment, at the left of the horizontal rule at bottom, you don't get such indenting although the test is the same and yields the same result/the same tokens, namely the tokens
\noindent~13\rule{1312c11m11}2{1112p11t11}2␣10\\?
The subtle point is:
At the start of the environment TeX is in vertical mode and has not yet started a new paragraph.
At the end of the environment the tokens forming the test-result are preceded by \\
, i.e., are preceded by directive for a line break within a paragraph whereafter TeX is in horizontal mode.
Let's look at ~
:
Active ~
, i.e., ~13 in LaTeX 2ε usually is defined to be a macro which expands to
\leavevmode\nobreak\␣.
\leavevmode in turn expands to \unhbox\voidb@x.
\nobreak in turn inserts a penalty of value 10000 which is sort of infinitely large for TeX.
So \noindent~13 is like \noindent \unhbox\voidb@x \penalty112012012012012\relax \␣.
Notice the control-space, \␣, at the end?
The TeXbook says a few things about the control-space:
In "Chapter 25: Summary of Horizontal Mode" you find:
\␣
. A control-space command appends glue to the current list, using the same amount that a ⟨space token⟩ inserts when the space factor is 1000.
In "Chapter 13: Modes", somewhere right after exercise 13.1, you find:
A control space (\␣
) will, however, be regarded as the beginning of a paragraph; the paragraph will start with a blank space after the indentation.
That's why at the begin of the environment, which is also the beginning of the paragraph, you get that additional indenting.
In "Chapter 14: How TeX Breaks Paragraphs into Lines" you find:
When a line break actually does occur, TeX removes all discardable items that follow the break, until coming to something non-discardable, or until coming
to another chosen breakpoint.
\\
causes a linebreak within a paragraph while \noindent
does nothing in horizontal mode and all things coming from ~
are either void or discardable.
That's why at the end of the environment the space/horizontal glue coming from ~
is discarded and you don't get the additional indenting.
\IfNoValueTF
is designed for use witho
notO
. It tests for a special no-value token which the code produces if ano
-type argument is omitted. the absence of an optional argument is not the same as the presence of either a blank or empty argument.\foo
and\foo[]
are then not the same as the first give #1 = NULL the other sets #1 = "". But O{} always sets #1 = "" initially, so a test against NULL would make no sense.~\\~A
, A has no space. So the question is actually the opposite, why is the~
not ignored at the start of the env.~\noindent
and\\~\noindent
are incorrect input, so the output is a bit arbitrary anyway. but\\
ignores following spaces by design.\` as white space is discarded after a line break, it would be discarded in vertical mode at the start of a paragraph too, but the paragraph is already started by
\noindent` in the begin code. (the\noindent
in teh end code does nothing as it is within the paragraph)