7

I am trying to compose a command into a token list.

\documentclass{article}
\usepackage{expl3}
\begin{document}
  \ExplSyntaxOn
  \tl_new:N \__a
  \tl_new:N \__b
  \tl_new:N \__c
  \tl_set:Nn \__a { test }
  \tl_set:Nn \__b { \{ }  % works with { brace } but not with { \{ }
  \tl_put_right:Nx \__c { \exp_not:N \m { \__a } { \__b } }
  \tl_show:N \__c % expected result: \m{test}{\{}
  \ExplSyntaxOff
\end{document}

Everything worked fine, but when I have a \{ token, the whole thing breaks. Any ideas how to solve this?

user41056
  • 115
  • \{ doesn't survive \edef, so it can't appear where full expansion is made. In LaTeX3 (when fully available) it will. – egreg Nov 14 '13 at 23:36
  • Hmm. Any other idea? Could I test for { in advance and replace it by something different that - in the end, when \m renders - creates a curly brace? – user41056 Nov 14 '13 at 23:59

1 Answers1

6

Commands such as \{ are to be used with care because they are defined with \DeclareRobustCommand. The expansion of \{ is

\x@protect \{\protect \{

and this is a sure sign that using it in an x argument is doomed to failure.

You could redefine

\protected\def\{{\ifmmode \lbrace \else \textbraceleft \fi}

and it would work; in xparse parlance it would be

\DeclareDocumentCommand \{ { }
 {
  \mode_if_math:TF { \lbrace } { \textbraceleft }
 }

and this would survive x expansion. One of the tasks waiting the LaTeX3 team is to redefine all such commands with ‘\protected’ macros instead of \DeclareRobustCommand. The reason is that \protected wasn't available when LaTeX2e was developed: it's one of the e-TeX extensions.

It would be a huge task to redefine all robust commands (\textbraceleft would need a rather different treatment). You can safely expand one level only, but probably you should take a different approach.

\documentclass{article}
\usepackage{expl3}
\begin{document}
  \ExplSyntaxOn
  \tl_new:N \__my_a_tl
  \tl_new:N \__my_b_tl
  \tl_new:N \__my_c_tl
  \tl_set:Nn \__my_a_tl { test }
  \tl_set:Nn \__my_b_tl { \{ }
  \tl_put_right:Nx \__my_c_tl
   {
    \exp_not:N \m { \exp_not:V \__my_a_tl } { \exp_not:V \__my_b_tl }
   }
  \tl_show:N \__my_c_tl % expected result: \m{test}{\{}
  \ExplSyntaxOff
\end{document}

Output on terminal:

> \__my_c_tl=macro:
->\m {test}{\{}.
egreg
  • 1,121,712
  • Wow, cool. \exp_not:V does the trick. I tried so many times with \exp_not:N and was so very close. – user41056 Nov 15 '13 at 07:00
  • @user41056 It means: get the value of the following variable and pass the result like it was \exp_not:n { <value> } – egreg Nov 15 '13 at 10:19