\documentclass{article}
% RN. 09 Feb 2017
% BRIEF DESCRIPTION:
% \cs_ functions are defined for a number of parameters. Evidently there is no
% provision of defining parameters for which arguments are optional (as there
% is in \NewDocumentCommands), but it seems that when a \cs_ function is called,
% trailing arguments are allowed to be missing, either (a) by being represented
% in the call through an empty pair of braces {}, or (b) with the argument missing
% altogether in the call. An empty pair of braces, case (a), is recognised in the
% \cs_ function's internal code both as "blank" and as "empty", however an
% argument missing altogether, case (b), is not recognized as a "-noValue-"
% condition as one might have expected. Is there any way to identify missing
% arguments in case (b)?
%=======================
\usepackage{comment}
\usepackage[check-declarations]{expl3}
\usepackage{xparse}
%-----------------------
\ExplSyntaxOn
% Variable Declarations:
\tl_new:N \l_rn_auxOne_tl
\tl_new:N \l_rn_auxTwo_tl
\tl_new:N \l_rn_auxThree_tl
\tl_new:N \g_rn_message_tl
\NewDocumentCommand\myTESTFunctionCalls{O{dsf134t}O{AAA}O{235711131719}}
% RN. Thursday 9 Feb 2017
% PARAMETERS: #1 tl,#2 tl,#3 tl
% BRIEF DESCRIPTION: calls a \cs function and investigates what happens if parameters
% are missing in calls, (a) by being represented through an empty pair of braces {},
% or (b) missing altogether.
{
\group_begin:
\textbf{Call~1.~\textbackslash rn\_ someFunction:nnn \{\#1\}\{\#2\}\{\#3\}~~:}\\
\rn_someFunction:nnn {#1}{#2}{#3}
\textbf{Call~2.~\textbackslash rn\_ someFunction:nnn \{\#1\}\{\}\{\#3\}~~:}\\
\rn_someFunction:nnn {#1}{}{#3}
\textbf{Call~3.~\textbackslash rn\_ someFunction:nnn \{\#1\}\{\#2\}~~:}\\
\rn_someFunction:nnn {#1}{#2}
\group_end:
} % \myTESTFunctionCall
\cs_new:Npn \rn_someFunction:nnn #1#2#3
% RN. Thursday 9 Feb 2017
% PARAMETERS: #1 tl, #2 tl, #3 tl
% RETURNS: none
{
\group_begin:
% processing argument #1:
\rn_argPreprocessor:nn {#1}{\g_rn_message_tl}
\tl_set:Nn \l_rn_auxOne_tl {#1}
\tl_gput_left:Nn \g_rn_message_tl {argument~1~received:~}
\tl_gput_right:Nn \g_rn_message_tl {\l_rn_auxOne_tl}
\g_rn_message_tl \\
% processing argument #2:
\rn_argPreprocessor:nn {#2}{\g_rn_message_tl}
\tl_set:Nn \l_rn_auxTwo_tl {#2}
\tl_gput_left:Nn \g_rn_message_tl {argument~2~received:~}
\tl_gput_right:Nn \g_rn_message_tl {\l_rn_auxTwo_tl}
\g_rn_message_tl \\
% processing argument #3:
\rn_argPreprocessor:nn {#3}{\g_rn_message_tl}
\tl_set:Nn \l_rn_auxThree_tl {#3}
\tl_gput_left:Nn \g_rn_message_tl {argument~3~received:~}
\tl_gput_right:Nn \g_rn_message_tl {\l_rn_auxThree_tl}
\g_rn_message_tl \\
\group_end:
} % \rn_someFunction:nnn
\cs_new:Npn \rn_argPreprocessor:nn #1#2
% just a little Helper function
{
\group_begin:
\tl_gclear:N #2
\IfNoValueTF {#1}
{\tl_gput_right:Nn #2 {-NoValue-~}}
{
\tl_if_blank:nTF {#1}
{\tl_gput_right:Nn #2 {\textbf{blank}}}
{}
\tl_if_empty:nTF {#1}
{\tl_gput_right:Nn #2 {\textbf{,~empty}}}
{}
}
\group_end:
} % \rn_argPreprocessor:nn
\ExplSyntaxOff
%-----------------------
\begin{document}
\myTESTFunctionCalls
\end{document}
答案1
您的复杂代码可以归结为:
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new_protected:Nn \test_function:nnn
{
\tl_show:n { \#1=#1,~\#2=#2,~#3=#3}
}
\group_begin:
\test_function:nnn { A } { B } { C }
\test_function:nnn { A } { B }
\group_end:
当以交互方式运行时,
> \#1=A, \#2=B, C=C.
<recently read> }
l.12 \test_function:nnn { A } { B } { C }
?
> \#1=A, \#2=B, \group_end: =\group_end: .
<recently read> }
l.14 \group_end:
TeX 宏没有区别,因为这些是TeX 宏的开始和参数解析如 TeXbook 中所述。
在您的代码中,最后一次调用\rn_someFunction:nnn
是
\rn_someFunction:nnn {#1}{#2}
\group_end:
第三个参数是\group_end:
。
如果没有\group_end:
,输入流中的下一个标记或括号组将被视为“缺少的参数”,如果下一个标记作为参数无效(例如,如果它是}
),则可能会出错。