expl3
inclui os especificadores de argumento o
, f
e x
para expansão de um nível e dois tipos de expansão completa, respectivamente, antes de passar o argumento para a função base. Qual é a forma preferida de expandir um argumentoduas vezesantes de passá-lo para a função base?
Por exemplo, estou tentando escrever uma l3keys
interface de valor-chave para macros criadas a \DeclarePairedDelimiter
partir do mathtools
pacote.
\tl_new:N \l__mymodule_size_tl
\keys_define:nn { mymodule }
{
size .choices:nn =
{ big , Big , bigg , Bigg }
{
\tl_set:Nn \l__mymodule_size_tl
{ [ \use:c { \tl_use:N \l_keys_choice_tl } ] }
} ,
size / auto .code:n =
\tl_set:Nn \l__mymodule_size_tl {*} ,
size / none .code:n =
\tl_clear:N \l__mymodule_size_tl
}
Normalmente, o tamanho dos delimitadores é passado para a macro como um argumento opcional de \big
etc. ou *
, como \abs[\big]{x}
where \DeclarePairedDelimiter\abs{\lvert}{\rvert}
. Eu preferiria ter size = big
etc. ou size = auto
como uma interface de valor-chave, como \myabs[size=big]{x}
.
O problema com o código acima está na configuração correta \l__mymodule_size_tl
nas big
opções etc.: preciso expandir[ \use:c { \tl_use:N \l_keys_choice_tl } ]
duas vezesantes de atribuir esses tokens a \l__mymodule_size_tl
.
- Se eu não usar nenhuma expansão (ou seja,
\tl_set:Nn
), a chamada para\abs
obterá seu argumento na forma errada -\l__mymodule_size_tl
será válida[ \use:c { \tl_use:N \l_keys_choice_tl } ]
, não[\big]
. - Se eu usar a expansão de um nível (ou seja,
\tl_set:No
) e acrescentar[
após a conclusão da expansão,\l__mymodule_size_tl
será mantido[ \cs:w \tl_use:N \l_keys_choice_tl \cs_end: ]
, não[\big]
. - Se eu usar uma
f
ou outrax
expansão,\l__mymodule_size_tl
vai conter um monte de "lixo", não[\big]
.
O que posso fazer? Aqui está uma ideia: use duas o
expansões, com algumas acrobacias entre elas.
\tl_set:No \l__mymodule_size_tl
{ \use:c { \tl_use:N \l_keys_choice_tl } ] }
\exp_args:NNV \tl_set:No \l__mymodule_size_tl
\l__mymodule_size_tl
\tl_put_left:Nn \l__mymodule_size_tl { [ }
Isso é bastante feio, na minha opinião. Existe algo melhor que eu possa fazer?
Responder1
Antigamente, havia um d
argumento do tipo -para a expansão dupla. No entanto, foi abandonado há alguns anos porque havia poucos locais onde era necessário, especialmente quando a equipa decidiu não utilizar toks
registos de forma geral. De memória, expl3
há dois lugares onde tivemos que ir com uma construção da \exp_args:NNo \exp_args:No
forma ou similar.
A razão pela qual não mantivemos d
os argumentos -type é dupla. Primeiro, queremos evitar, sempre que possível, depender do conhecimento dos detalhes de expansão das funções: isto é necessário para trabalhos de baixo nível, mas idealmente deveria ser relativamente limitado. A outra razão é que raramente é necessário, pois temos o e-TeX disponível. A chave a lembrar é que isso nos permite controlar a expansão em x
contextos do tipo -
\tl_set:Nx \l__mymodule_size_tl
{ [ \exp_not:c { \tl_use:N \l_keys_choice_tl } ] }
Embora não seja necessário aqui, documentamos \cs:w
... \cs_end:
para situações em que exatamente uma expansão é necessária, para que você possa ter
\tl_set:No \l__mymodule_size_tl
{ \exp_after:wN [ \cs:w \tl_use:N \l_keys_choice_tl \cs_end: ] }
embora eu não usasse isso aqui sozinho.
Responder2
Minha impressão é que você quer fazer
\tl_set:Nx \l__mymodule_size_tl
{
[ \exp_not:c { \tl_use:N \l_keys_choice_tl } ]
}
Com x
a expansão \exp_not:c
é acionada, então o argumento é totalmente expandido como sempre quando c
está envolvido (é \csname...\endcsname
); então o token resultante não é expansível, então se você tiver
size=big
você entrará [\big]
em sua lista de tokens.