Qual é a forma preferida de expandir duas vezes no expl3?

Qual é a forma preferida de expandir duas vezes no expl3?

expl3inclui os especificadores de argumento o, fe xpara 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 l3keysinterface de valor-chave para macros criadas a \DeclarePairedDelimiterpartir do mathtoolspacote.

\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 \bigetc. ou *, como \abs[\big]{x}where \DeclarePairedDelimiter\abs{\lvert}{\rvert}. Eu preferiria ter size = bigetc. ou size = autocomo 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_tlnas bigopçõ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 \absobterá seu argumento na forma errada - \l__mymodule_size_tlserá 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_tlserá mantido [ \cs:w \tl_use:N \l_keys_choice_tl \cs_end: ], não [\big].
  • Se eu usar uma fou outra xexpansão, \l__mymodule_size_tlvai conter um monte de "lixo", não [\big].

O que posso fazer? Aqui está uma ideia: use duas oexpansõ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 dargumento 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 toksregistos de forma geral. De memória, expl3há dois lugares onde tivemos que ir com uma construção da \exp_args:NNo \exp_args:Noforma ou similar.

A razão pela qual não mantivemos dos 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 xcontextos 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 xa expansão \exp_not:cé acionada, então o argumento é totalmente expandido como sempre quando cestá 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.

informação relacionada