我需要能够将[ ]
(中间带有空格的括号)传递给 a\def
并检查 的\def
参数是否包含[ ]
(而不是其他内容)。
\begin{document}
\def\bptoks{[ ]}
\def\bpdef#1
{ \ifx#1\string\bptoks % DOESN'T WORK
square brackets
\else
something else
\fi
}
\bpdef{[ ]} % OUTPUT: something else
\end{document}
编辑:
\bptoks
不会在 处展开\ifx
,所以我尝试了\ifx\detokenize{#1}\detokenize{[ ]}
但又出错了。我认为这是因为\ifx
检查单个标记,我不知道如何让它改为检查标记列表。此外,\detokenize{#1}
可能会将其视为#1
字符串(我不知道)。
答案1
\ifx
比较两个不带扩展的标记,因此如果您传递[ ]
给\bpdef
,\ifx
测试将[
与空格进行比较并失败。您需要定义一个临时宏并将其与 进行比较\bptoks
。或者,您可以使用\pdfstrcmp
(或其他引擎中的等效宏(\pdf@strcmp
如果您加载pdftexcmds
))进行字符串比较:
\documentclass{article}
\usepackage{pdftexcmds}
\makeatletter
\let\bpstrcmp\pdf@strcmp
\makeatother
\begin{document}
\def\bptoks{[ ]}
\def\bpdef#1%
{%
\def\bptmpa{#1}%
\ifx\bptmpa\bptoks % DOESN'T WORK
square brackets
\else
something else
\fi
}
\bpdef{[ ]}\par % OUTPUT: square brackets
\bpdef{] [}\par % OUTPUT: something else
\def\bpdef#1%
{%
\ifnum\bpstrcmp{#1}{\bptoks}=0
square brackets
\else
something else
\fi
}
\bpdef{[ ]}\par % OUTPUT: square brackets
\bpdef{] [}\par % OUTPUT: something else
\end{document}
还要记住\ifx
比较代币,而不是字符,因此如果您在一个 catcode 设置中定义并在使用 时更改、或\bptoks
的 catcode ,则测试也会失败。试试这个:[
]
\bpdef
\ifx
\catcode`\[=12
\def\bptoks{[ ]}
\catcode`\[=1
\bpdef{[ ]} % OUTPUT: something else
此外,您的定义是:
\def\bpdef#1
{ ... }
这与以下内容相同:
\def\bpdef#1 { ... }
这要求在使用\bpdef
宏时必须在第一个参数后加一个空格,这样\bpdef{[]} \par
就可以了,但\bpdef{[]}\par
不行。我添加了一个%
来删除它。
关于你问题的最后一段:是的,\ifx
正如我已经提到的那样,不会展开,这意味着当你执行 时\ifx\detokenize{#1}\detokenize{[ ]}
,\ifx
比较\detokenize
和{
并得出 false。但不,\detokenize{#1}
实际上是\detokenize{<actual-argument>}
。参数替换发生在扩展时,而制作\bpdef
的扩展(已被替换为或任何其他)只会在稍后发生。\detokenize
#1
[ ]
答案2
(这是我的回答的第一部分,它由两部分组成。这是我的答案第二部分的链接。)
您也可以通过分隔参数来实现此类测试。
对于仅基于分隔参数的测试,不\if
应用任何 -switch,因此此类测试不会被不平衡\else
或\fi
或\endcsname
之类的因素所欺骗。
对于仅基于分隔参数的测试,在执行测试时不会发生临时赋值/不会定义临时宏。因此,它们也在扩展上下文中工作,即,它们也在 -construct 内部\edef
或从 -construct 内部执行时工作\csname..\endcsname
。
\documentclass{article}
\makeatletter
%%=============================================================================
%% Paraphernalia:
%% \UD@firstoftwo, \UD@secondoftwo,
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
\UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
\UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no exclamation mark which is not nested
%% in braces:
%%.............................................................................
%% \UD@CheckWhetherNoExclam{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% contains no exclamation mark>}%
%% {<Tokens to be delivered in case that argument
%% contains exclamation mark>}%
%%
\newcommand\UD@GobbleToExclam{}\long\def\UD@GobbleToExclam#1!{}%
\newcommand\UD@CheckWhetherNoExclam[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToExclam#1!}%
}%
%%-----------------------------------------------------------------------------
%% \UD@SpaceInBracketsFork grabs the first undelimited argument behind a
%% token-sequence of pattern !![ ]! and removes everything between that
%% undelimited argument and a following sequence !!!! .
%%.............................................................................
\newcommand\UD@SpaceInBracketsFork{}
\long\def\UD@SpaceInBracketsFork#1!![ ]!#2#3!!!!{#2}%
%%-----------------------------------------------------------------------------
%% Check whether argument consists only of the token-sequence [ ]:
%% In expansion-contexts the check delivers the result after exactly two
%% expansion-steps/after exactly two "hits" by \expandafter.
%%.............................................................................
\newcommand\UD@CheckWhetherSpaceInBrackets[1]{%
\romannumeral0% <- romannumeral is used only for triggering expansion until
% in the end finding a space token trailing the `0` and thus
% finding a non-positive number and thus - after nicely doing
% a lot of expansion-work - silently not delivering any token
% at all.
\UD@CheckWhetherNoExclam{#1}{%
\UD@SpaceInBracketsFork
%Case #1 is empty/has no tokens:
!#1![ ]!{\UD@secondoftwo{}{\expandafter} \UD@secondoftwo}%
%Case #1 = [ ]
!!#1!{\UD@secondoftwo{}{\expandafter} \UD@firstoftwo}%
%Case #1 = something else without exclamation-mark:
!![ ]!{\UD@secondoftwo{}{\expandafter} \UD@secondoftwo}%
!!!!%
}{%
%Case #1 = something else with exclamation-mark:
\UD@secondoftwo{}{\expandafter} \UD@secondoftwo
}%
}%
%%-----------------------------------------------------------------------------
\newcommand\bpdef[1]{%
\UD@CheckWhetherSpaceInBrackets{#1}{square brackets}{something else}%
}%
\makeatother
\begin{document}
1) \verb*|\bpdef{[ ]}|: \bpdef{[ ]}
2) \verb*|\bpdef{ [ ]}|: \bpdef{ [ ]}
3) \verb*|\bpdef{[ ] }|: \bpdef{[ ] }
4) \verb*|\bpdef{ [ ] }|: \bpdef{ [ ] }
5) \verb*|\bpdef{}|: \bpdef{}
6) \verb*|\bpdef{bla}|: \bpdef{bla}
7) \verb*|\bpdef{!![ ]!!!!!!}|: \bpdef{!![ ]!!!!!!}
\end{document}
顺便一提:使用这种方法,你可以同时检查几个不同的标记序列:
\documentclass{article}
\makeatletter
%%=============================================================================
%% Paraphernalia:
%% \UD@firstoftwo, \UD@secondoftwo,
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
\UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
\UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no exclamation mark which is not nested
%% in braces:
%%.............................................................................
%% \UD@CheckWhetherNoExclam{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% contains no exclamation mark>}%
%% {<Tokens to be delivered in case that argument
%% contains exclamation mark>}%
%%
\newcommand\UD@GobbleToExclam{}\long\def\UD@GobbleToExclam#1!{}%
\newcommand\UD@CheckWhetherNoExclam[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToExclam#1!}%
}%
%%-----------------------------------------------------------------------------
%% \UD@FlowersFork grabs the first undelimited argument behind a
%% token-sequence of pattern
%% !!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!
%% and removes everything between that undelimited argument and a following sequence !!!! .
%%.............................................................................
\newcommand\UD@FlowersFork{}
\long\def\UD@FlowersFork#1!!%
Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!%
Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
#2#3!!!!{#2}%
%%-----------------------------------------------------------------------------
%% Fork whether argument either is empty or is "Rose" or is "Lily" or is "Tulip"
%% or is "Orchid" or is "Carnation" or is "Hyacinth" or is "Peruvian Lily" or is
%% "Chrysanthemum" or is "Gladiolus" or is "Anemone" or is "Daffodil" or is "Sunflower"
%% or is something else without exclamation-mark or is something else with exclamation-mark.
%%
%% In expansion-contexts the forking-mechanism delivers the result after exactly two
%% expansion-steps/after exactly two "hits" by \expandafter.
%%.............................................................................
\newcommand\Flowerfork[1]{%
\romannumeral0% <- romannumeral is used only for triggering expansion until
% in the end finding a space token trailing the `0` and thus
% finding a non-positive number and thus - after nicely doing
% a lot of expansion-work - silently not delivering any token
% at all.
\UD@CheckWhetherNoExclam{#1}{%
\UD@FlowersFork
!#1!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{ Case: Argument is empty.}%
!!#1!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{ Case: Argument is ``Rose''.}%
!!Rose!#1!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{ Case: Argument is ``Lily''}%
!!Rose!Lily!#1!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{ Case: Argument is ``Tulip''}%
!!Rose!Lily!Tulip!#1!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{ Case: Argument is ``Orchid''}%
!!Rose!Lily!Tulip!Orchid!#1!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{ Case: Argument is ``Carnation''}%
!!Rose!Lily!Tulip!Orchid!Carnation!#1!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{ Case: Argument is ``Hyacinth''}%
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!#1!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{ Case: Argument is ``Peruvian Lily''}%
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!#1!Gladiolus!Anemone!Daffodil!Sunflower!%
{ Case: Argument is ``Chrysanthemum''}%
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!#1!Anemone!Daffodil!Sunflower!%
{ Case: Argument is ``Gladiolus''}%
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!#1!Daffodil!Sunflower!%
{ Case: Argument is ``Anemone''}%
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!#1!Sunflower!%
{ Case: Argument is ``Daffodil''}%
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!#1!%
{ Case: Argument is ``Sunflower''}%
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{ Case: Argument is something else which does not contain an exclamation mark.}%
!!!!%
}{ %
Case: Argument is something else which does contain some exclamation mark(s).%
}%
}%
\makeatother
\begin{document}
01) \verb*|\Flowerfork{Rose}|: \Flowerfork{Rose}%
02) \verb*|\Flowerfork{Lily}|: \Flowerfork{Lily}%
03) \verb*|\Flowerfork{Tulip}|: \Flowerfork{Tulip}%
04) \verb*|\Flowerfork{Orchid}|: \Flowerfork{Orchid}%
05) \verb*|\Flowerfork{Carnation}|: \Flowerfork{Carnation}%
06) \verb*|\Flowerfork{Hyacinth}|: \Flowerfork{Hyacinth}%
07) \verb*|\Flowerfork{Peruvian Lily}|: \Flowerfork{Peruvian Lily}%
08) \verb*|\Flowerfork{Chrysanthemum}|: \Flowerfork{Chrysanthemum}%
09) \verb*|\Flowerfork{Gladiolus}|: \Flowerfork{Gladiolus}%
10) \verb*|\Flowerfork{Anemone}|: \Flowerfork{Anemone}%
11) \verb*|\Flowerfork{Daffodil}|: \Flowerfork{Daffodil}%
12) \verb*|\Flowerfork{Sunflower}|: \Flowerfork{Sunflower}%
13) \verb*|\Flowerfork{Something else without exclamation marks}|: \Flowerfork{Something else without exclamation marks}%
14) \verb*|\Flowerfork{!!Something else with exclamation marks}|: \Flowerfork{!!Something else witht exclamation marks}%
15) \verb*|\Flowerfork{ }|: \Flowerfork{ }%
16) \verb*|\Flowerfork{}|: \Flowerfork{}%
\end{document}
(这是我的回答的第一部分,它由两部分组成。这是我的答案第二部分的链接。)
答案3
(这是我的回答的第二部分,它由两部分组成。这是我的答案第一部分的链接。)
到目前为止,在不同情况下需要传递的令牌在宏定义中已经“硬连线”了。
但是,你可以将这种基于分隔参数的分叉机制与抓取无分隔参数列表的第 k 个元素的机制结合起来,从而可以通过针对每种情况的宏参数来指定每种情况下要传递的标记:
\documentclass[a4paper]{article}
\makeatletter
%%=============================================================================
%% Paraphernalia:
%% \UD@firstoftwo, \UD@secondoftwo,
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
%%=============================================================================
%% Check whether argument is empty:
%%=============================================================================
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
\UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
\UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%=============================================================================
%% Keep only the K-th of L consecutive undelimited arguments.
%% ( IF K < 1 OR K > L just remove L consecutive undelimited arguments. )
%%=============================================================================
%% \KeepKthOfLArguments{<integer number K>}%
%% {<integer number L>}%
%% <sequence of L consecutive undelimited arguments>
%%
%% If L < 1 yields nothing.
%% Else:
%% If K >= 1 and K <= L yields:
%% <K-th undelimited argument from <sequence of L consecutive undelimited
%% arguments>>
%% If K < 1 or K > L
%% (-> there is no K-th argument in the
%% <sequence of L consecutive undelimited arguments> )
%% yields nothing but removal of <sequence of L consecutive
%% undelimited arguments>
\newcommand\KeepKthOfLArguments[2]{%
\romannumeral0%
% #1: <integer number K>
% #2: <integer number L>
\expandafter\UD@KeepKthOfLArgumentsKSmallerOneFork
\expandafter{\romannumeral\number\number#1 000\expandafter}%
\expandafter{\romannumeral\number\number#2 000}%
}%
%%-----------------------------------------------------------------------------
\newcommand\UD@KeepKthOfLArgumentsKSmallerOneFork[2]{%
% #1: <K letters m>
% #2: <L letters m >
\UD@CheckWhetherNull{#1}{% K is smaller than one:
\UD@KeepKthOfLArgumentsRemoveNArguments{#2}{ }{}%
}{% K is not smaller than one:
\expandafter\UD@PassFirstToSecond
\expandafter{%
\UD@firstoftwo{}#1%
}{%
\UD@KeepKthOfLArgumentsEvaluateLMinusKDifferenceLoop{#1}{#2}%
}{#2}%
}%
}%
%%-----------------------------------------------------------------------------
\newcommand\UD@KeepKthOfLArgumentsEvaluateLMinusKDifferenceLoop[4]{%
% #1: <K letters m>
% #2: <L letters m>
% (For detecting whether K>L or K<=L, during the loop letters m will
% be removed both from #1 and #2 until at least one of these arguments
% is empty.
% When the loop terminates with 0<K<=L, #1 will be empty and #2
% will hold an amount of letters m corresponding to the the
% difference L-K.
% When the loop terminates with K>L, #1 will not be empty and #2
% will be empty.
% )
% #3: <K-1 letters m>
% #4: <L letters m>
% (#3 and #4 will be left untouched during the loop so they can be
% used for performing appropriate action when loop terminates as
% it is known whether K>L.)
\UD@CheckWhetherNull{#1}{% We have K<=L:
\UD@KeepKthOfLArgumentsRemoveNArguments{%
#3%
}{%
\UD@KeepKthOfLArgumentsRemoveNArguments{#2}{ }%
}{}%
}{%
\UD@CheckWhetherNull{#2}{% We have K>L:
\UD@KeepKthOfLArgumentsRemoveNArguments{#4}{ }{}%
}{% We don't know yet whether K<=L or K>L, thus remove letters m and
% do another iteration:
\expandafter\UD@PassFirstToSecond
\expandafter{%
\UD@firstoftwo{}#2%
}{%
\expandafter\UD@KeepKthOfLArgumentsEvaluateLMinusKDifferenceLoop
\expandafter{%
\UD@firstoftwo{}#1%
}%
}{#3}{#4}%
}%
}%
}%
%%-----------------------------------------------------------------------------
%% \UD@KeepKthOfLArgumentsRemoveNArguments{<N letters m>}%
%% {<argument 1>}%
%% {<argument 2>}%
%% <sequence of consecutive
%% undelimited arguments>
%%.............................................................................
%% Removes the first N undelimited arguments from the <sequence of
%% consecutive undelimited arguments>, then inserts
%% <argument 1><argument 2>
%%
%% On the one hand when providing <argument 2> empty, you can use
%% <argument 1> for nesting calls to \UD@KeepKthOfLArgumentsRemoveNArguments.
%% On the other hand you can provide a <space token> for stopping
%% \romannumeral-expansion as <argument 1> and have the
%% macro grab the <K-th undelimited argument> from the <sequence of L
%% consecutive undelimited arguments> as <argument 2>.
%%
\newcommand\UD@KeepKthOfLArgumentsRemoveNArguments[3]{%
%% #1: <N letters m>
%% #2: <Argument 1>
%% #3: <Argument 2>
\UD@CheckWhetherNull{#1}{#2#3}{%
\UD@firstoftwo{%
\expandafter\UD@KeepKthOfLArgumentsRemoveNArguments
\expandafter{%
\UD@firstoftwo{}#1%
}{#2}{#3}%
}%
}%
}%
%%-----------------------------------------------------------------------------
%% End of code for \KeepKthOfLArguments.
%%=============================================================================
%% Check whether argument contains no exclamation mark which is not nested
%% in braces:
%%=============================================================================
%% \UD@CheckWhetherNoExclam{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% contains no exclamation mark>}%
%% {<Tokens to be delivered in case that argument
%% contains exclamation mark>}%
%%
\newcommand\UD@GobbleToExclam{}\long\def\UD@GobbleToExclam#1!{}%
\newcommand\UD@CheckWhetherNoExclam[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToExclam#1!}%
}%
%%=============================================================================
%% Fork whether argument either is "Rose" or is "Lily" or is "Tulip" or is
%% "Orchid" or is "Carnation" or is "Hyacinth" or is "Peruvian Lily" or is
%% "Chrysanthemum" or is "Gladiolus" or is "Anemone" or is "Daffodil" or is
%% "Sunflower" or is empty or is something else.
%%
%% \Flowerfork processes 15 arguments. The syntax is:
%%
%% \Flowerfork{<argument to check>}% <- argument 1
%% {<tokens in case argument is "Rose">}% <- argument 2
%% {<tokens in case argument is "Lily">}% <- argument 3
%% {<tokens in case argument is "Tulip">}% <- argument 4
%% {<tokens in case argument is "Orchid">}% <- argument 5
%% {<tokens in case argument is "Carnation">}% <- argument 6
%% {<tokens in case argument is "Hyacinth">}% <- argument 7
%% {<tokens in case argument is "Peruvian Lily">}% <- argument 8
%% {<tokens in case argument is "Chrysanthemum">}% <- argument 9
%% {<tokens in case argument is "Gladiolus">}% <- argument 10
%% {<tokens in case argument is "Anemone">}% <- argument 11
%% {<tokens in case argument is "Daffodil">}% <- argument 12
%% {<tokens in case argument is "Sunflower">}% <- argument 13
%% {<tokens in case argument is "empty">}% <- argument 14
%% {<tokens in case argument is something else>}% <- argument 15
%%
%% In expansion-contexts the forking-mechanism delivers the result after exactly
%% two expansion-steps/after exactly two "hits" by \expandafter.
%%=============================================================================
\newcommand\Flowerfork[1]{%
\romannumeral% <- romannumeral is used only for triggering expansion...
\expandafter\UD@secondoftwo\KeepKthOfLArguments{%
\UD@CheckWhetherNoExclam{#1}{%
\UD@FlowersFork
!#1!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{13}%<-Case: Argument is empty.
!!#1!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{1}%<-Case: Argument is "Rose".
!!Rose!#1!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{2}%<-Case: Argument is "Lily"
!!Rose!Lily!#1!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{3}%<-Case: Argument is "Tulip"
!!Rose!Lily!Tulip!#1!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{4}%<-Case: Argument is "Orchid"
!!Rose!Lily!Tulip!Orchid!#1!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{5}%<-Case: Argument is "Carnation"
!!Rose!Lily!Tulip!Orchid!Carnation!#1!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{6}%<-Case: Argument is "Hyacinth"
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!#1!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{7}%<-Case: Argument is "Peruvian Lily"
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!#1!Gladiolus!Anemone!Daffodil!Sunflower!%
{8}%<-Case: Argument is "Chrysanthemum"
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!#1!Anemone!Daffodil!Sunflower!%
{9}%<-Case: Argument is "Gladiolus"
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!#1!Daffodil!Sunflower!%
{10}%<-Case: Argument is "Anemone"
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!#1!Sunflower!%
{11}%<-Case: Argument is "Daffodil"
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!#1!%
{12}%<-Case: Argument is "Sunflower"
!!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
{14}%<-Case: Argument is something else which does not contain an exclamation mark.
!!!!%
}{14}%<-Case: Argument is something else which does contain some exclamation mark(s).%
}{14}%
}%
%%-----------------------------------------------------------------------------
%% \UD@FlowersFork grabs the first undelimited argument behind a
%% token-sequence of pattern
%% !!Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!
%% and removes everything between that undelimited argument and a following sequence !!!! .
%%-----------------------------------------------------------------------------
\newcommand\UD@FlowersFork{}
\long\def\UD@FlowersFork#1!!%
Rose!Lily!Tulip!Orchid!Carnation!Hyacinth!Peruvian Lily!%
Chrysanthemum!Gladiolus!Anemone!Daffodil!Sunflower!%
#2#3!!!!{#2}%
\makeatother
% Paper and vertical layout of this example:
\expandafter\ifx\csname pdfpageheight\endcsname\relax\else
\pdfpageheight=\paperheight
\pdfpagewidth=\paperwidth
\fi
\expandafter\ifx\csname pageheight\endcsname\relax\else
\pageheight=\paperheight
\pagewidth=\paperwidth
\fi
\textheight=\paperheight
\advance\textheight by -5cm
\topmargin=2.5cm
\advance\topmargin by -1in
\headheight=0pt
\headsep=0pt
\footnotesep=1cm
%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
\footnotesize
\begin{verbatim}
\Flowerfork{Lily}%
{Tokens in case argument is ``Rose''.}%
{Tokens in case argument is ``Lily''.}%
{Tokens in case argument is ``Tulip''.}%
{Tokens in case argument is ``Orchid''.}%
{Tokens in case argument is ``Carnation''.}%
{Tokens in case argument is ``Hyacinth''.}%
{Tokens in case argument is ``Peruvian Lily''.}%
{Tokens in case argument is ``Chrysanthemum''.}%
{Tokens in case argument is ``Gladiolus''.}%
{Tokens in case argument is ``Anemone''.}%
{Tokens in case argument is ``Daffodil''.}%
{Tokens in case argument is ``Sunflower''.}%
{Tokens in case argument is empty.}%
{Tokens in case argument is something else.}%
\end{verbatim}
yields:
\Flowerfork{Lily}%
{Tokens in case argument is ``Rose''.}%
{Tokens in case argument is ``Lily''.}%
{Tokens in case argument is ``Tulip''.}%
{Tokens in case argument is ``Orchid''.}%
{Tokens in case argument is ``Carnation''.}%
{Tokens in case argument is ``Hyacinth''.}%
{Tokens in case argument is ``Peruvian Lily''.}%
{Tokens in case argument is ``Chrysanthemum''.}%
{Tokens in case argument is ``Gladiolus''.}%
{Tokens in case argument is ``Anemone''.}%
{Tokens in case argument is ``Daffodil''.}%
{Tokens in case argument is ``Sunflower''.}%
{Tokens in case argument is empty.}%
{Tokens in case argument is something else.}%
\noindent\null\hrulefill\null
\begin{verbatim}
\Flowerfork{Whatsoever / something else}%
{Tokens in case argument is ``Rose''.}%
{Tokens in case argument is ``Lily''.}%
{Tokens in case argument is ``Tulip''.}%
{Tokens in case argument is ``Orchid''.}%
{Tokens in case argument is ``Carnation''.}%
{Tokens in case argument is ``Hyacinth''.}%
{Tokens in case argument is ``Peruvian Lily''.}%
{Tokens in case argument is ``Chrysanthemum''.}%
{Tokens in case argument is ``Gladiolus''.}%
{Tokens in case argument is ``Anemone''.}%
{Tokens in case argument is ``Daffodil''.}%
{Tokens in case argument is ``Sunflower''.}%
{Tokens in case argument is empty.}%
{Tokens in case argument is something else.}%
\end{verbatim}
yields:
\Flowerfork{Whatsoever / something else}%
{Tokens in case argument is ``Rose''.}%
{Tokens in case argument is ``Lily''.}%
{Tokens in case argument is ``Tulip''.}%
{Tokens in case argument is ``Orchid''.}%
{Tokens in case argument is ``Carnation''.}%
{Tokens in case argument is ``Hyacinth''.}%
{Tokens in case argument is ``Peruvian Lily''.}%
{Tokens in case argument is ``Chrysanthemum''.}%
{Tokens in case argument is ``Gladiolus''.}%
{Tokens in case argument is ``Anemone''.}%
{Tokens in case argument is ``Daffodil''.}%
{Tokens in case argument is ``Sunflower''.}%
{Tokens in case argument is empty.}%
{Tokens in case argument is something else.}%
\noindent\null\hrulefill\null
\newpage
\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\test
\expandafter\expandafter\expandafter{%
\Flowerfork{Rose}%
{Tokens in case argument is ``Rose''.}%
{Tokens in case argument is ``Lily''.}%
{Tokens in case argument is ``Tulip''.}%
{Tokens in case argument is ``Orchid''.}%
{Tokens in case argument is ``Carnation''.}%
{Tokens in case argument is ``Hyacinth''.}%
{Tokens in case argument is ``Peruvian Lily''.}%
{Tokens in case argument is ``Chrysanthemum''.}%
{Tokens in case argument is ``Gladiolus''.}%
{Tokens in case argument is ``Anemone''.}%
{Tokens in case argument is ``Daffodil''.}%
{Tokens in case argument is ``Sunflower''.}%
{Tokens in case argument is empty.}%
{Tokens in case argument is something else.}%
}%
\end{verbatim}
yields:
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\test
\expandafter\expandafter\expandafter{%
\Flowerfork{Rose}%
{Tokens in case argument is ``Rose''.}%
{Tokens in case argument is ``Lily''.}%
{Tokens in case argument is ``Tulip''.}%
{Tokens in case argument is ``Orchid''.}%
{Tokens in case argument is ``Carnation''.}%
{Tokens in case argument is ``Hyacinth''.}%
{Tokens in case argument is ``Peruvian Lily''.}%
{Tokens in case argument is ``Chrysanthemum''.}%
{Tokens in case argument is ``Gladiolus''.}%
{Tokens in case argument is ``Anemone''.}%
{Tokens in case argument is ``Daffodil''.}%
{Tokens in case argument is ``Sunflower''.}%
{Tokens in case argument is empty.}%
{Tokens in case argument is something else.}%
}%
\texttt{\string\test: \meaning\test}%
\noindent\null\hrulefill\null
\begin{verbatim}
\newcommand*\MyRoseCommand{This comes from \texttt{\string\MyRoseCommand}.}%
\newcommand*\MyLilyCommand{This comes from \texttt{\string\MyLilyCommand}.}%
\newcommand*\MyTulipCommand{This comes from \texttt{\string\MyTulipCommand}.}%
\newcommand*\MyOrchidCommand{This comes from \texttt{\string\MyOrchidCommand}.}%
\newcommand*\MyCarnationCommand{This comes from \texttt{\string\MyCarnationCommand}.}%
\newcommand*\MyHyacinthCommand{This comes from \texttt{\string\MyHyacinthCommand}.}%
\newcommand*\MyPeruvianLilyCommand{This comes from \texttt{\string\MyPeruvianLilyCommand}.}%
\newcommand*\MyChrysanthemumCommand{This comes from \texttt{\string\MyChrysanthemumCommand}.}%
\newcommand*\MyGladiolusCommand{This comes from \texttt{\string\MyGladiolusCommand}.}%
\newcommand*\MyAnemoneCommand{This comes from \texttt{\string\MyAnemoneCommand}.}%
\newcommand*\MyDaffodilCommand{This comes from \texttt{\string\MyDaffodilCommand}.}%
\newcommand*\MySunflowerCommand{This comes from \texttt{\string\MySunflowerCommand}.}%
\newcommand*\MyEmptyCommand{This comes from \texttt{\string\MyEmptyCommand}.}%
\newcommand*\MySomethingElseCommand{This comes from \texttt{\string\MySomethingElseCommand}.}%
\end{verbatim}
\newcommand*\MyRoseCommand{This comes from \texttt{\string\MyRoseCommand}.}%
\newcommand*\MyLilyCommand{This comes from \texttt{\string\MyLilyCommand}.}%
\newcommand*\MyTulipCommand{This comes from \texttt{\string\MyTulipCommand}.}%
\newcommand*\MyOrchidCommand{This comes from \texttt{\string\MyOrchidCommand}.}%
\newcommand*\MyCarnationCommand{This comes from \texttt{\string\MyCarnationCommand}.}%
\newcommand*\MyHyacinthCommand{This comes from \texttt{\string\MyHyacinthCommand}.}%
\newcommand*\MyPeruvianLilyCommand{This comes from \texttt{\string\MyPeruvianLilyCommand}.}%
\newcommand*\MyChrysanthemumCommand{This comes from \texttt{\string\MyChrysanthemumCommand}.}%
\newcommand*\MyGladiolusCommand{This comes from \texttt{\string\MyGladiolusCommand}.}%
\newcommand*\MyAnemoneCommand{This comes from \texttt{\string\MyAnemoneCommand}.}%
\newcommand*\MyDaffodilCommand{This comes from \texttt{\string\MyDaffodilCommand}.}%
\newcommand*\MySunflowerCommand{This comes from \texttt{\string\MySunflowerCommand}.}%
\newcommand*\MyEmptyCommand{This comes from \texttt{\string\MyEmptyCommand}.}%
\newcommand*\MySomethingElseCommand{This comes from \texttt{\string\MySomethingElseCommand}.}%
\begin{verbatim}
\csname My\Flowerfork{Tulip}%
{Rose}{Lily}{Tulip}{Orchid}{Carnation}{Hyacinth}{PeruvianLily}{Chrysanthemum}%
{Gladiolus}{Anemone}{Daffodil}{Sunflower}{Empty}{SomethingElse}Command\endcsname
\end{verbatim}
yields:
\csname My\Flowerfork{Tulip}%
{Rose}{Lily}{Tulip}{Orchid}{Carnation}{Hyacinth}{PeruvianLily}{Chrysanthemum}%
{Gladiolus}{Anemone}{Daffodil}{Sunflower}{Empty}{SomethingElse}Command\endcsname
\end{document}
(这是我的回答的第二部分,它由两部分组成。这是我的答案第一部分的链接。)