下面的代码说明了我遇到的问题。似乎我不能直接在需要标记列表的地方使用标记列表变量,但为什么呢?我怎样才能得到我想要的结果?
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\bool_new:N \found_bool
\cs_new_protected:Npn \find_token_in_tl:Nn #1#2
{
\bool_set_false:N \found_bool
\tl_map_inline:nn { #2 }
{
\token_if_eq_charcode:NNT ##1 #1
{
\bool_set_true:N \found_bool
\tl_map_break:
}
}
}
\NewDocumentCommand { \FindTokInList } { m m }
{
\find_token_in_tl:Nn #1 {#2}
\bool_if:NTF \found_bool { ! } { ? }
}
\tl_const:Nn \punct_tl {,.;:}
\NewDocumentCommand { \FindTokInPunctList } { m }
{
\find_token_in_tl:Nn #1 \punct_tl
\bool_if:NTF \found_bool { ! } { ? }
}
\ExplSyntaxOff
\begin{document}
dot: \FindTokInList{.}{,.;:} % finds token & prints “!”
x: \FindTokInList{x}{,.;:} % doesn’t find token & prints “?”
dot: \FindTokInPunctList{.} % doesn’t find token & prints “?”, but why?
x: \FindTokInPunctList{x} % doesn’t find token & prints “?”
\end{document}
答案1
有标记列表和标记列表变量,分别是n
和N
类型。LaTeX3 编程层会小心不要扩展任何不该扩展的内容,因此当你这样做时
\tl_map_inline:nn {#2} { <code> }
=#2
你\l_JS_punct_tl
将单个标记传递\l_JS_punct_tl
给<code>
,不是变量的内容。为此,您需要
\tl_map_inline:Nn #2 { <code> }
您还可以使用以下方式传递值
\cs_generate_variant:Nn \tl_map_inline:nn { V }
\tl_map_inline:Vn #2 { <code> }
但这不是必需的。
另外,LaTeX3 代码变量应始终命名为
\<scope>_<module>_<description>_<type>
所以我在问题中使用了\l_JS_punct_tl
来代替。\punct_tl
答案2
已经有\tl_if_in:nnTF
和\tl_if_in:NnTF
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand { \FindTokInList } { m m }
{
\tl_if_in:nnTF {#2} {#1} { ! } { ? }
}
\tl_const:Nn \c_JS_punct_tl {,.;:}
\NewDocumentCommand { \FindTokInPunctList } { m }
{
\tl_if_in:NnTF \c_JS_punct_tl { #1 } { ! } { ? }
}
\ExplSyntaxOff
\begin{document}
dot: \FindTokInList{.}{,.;:} % finds token & prints !
x: \FindTokInList{x}{,.;:} % doesn't find token & prints ?
dot: \FindTokInPunctList{.} % finds token & prints !
x: \FindTokInPunctList{x} % doesn't find token & prints ?
\end{document}