5

I am using \csdef{} to define a meaning to a given open/close bracket:

\csdef{Bracket Meaning \CsToStr{\lvert}}{Left |}
\csdef{Bracket Meaning \CsToStr{\rvert}}{Right |}
\csdef{Bracket Meaning \CsToStr{(}}{open (}
\csdef{Bracket Meaning \CsToStr{)}}{close )}

The first two and the last seem to work just fine, but the third one has an issue. When I attempt to access these via #1~\csuse{Bracket Meaning \CsToStr{#1}} (where #1 is one of the four given brackets \lvert, \rvert, ( and ), the output is:

enter image description here

I had expected the one highlighted in red to be ( open (.

So, what is going on here, and how should I restructure this to obtain the desired result for the ( bracket?

Code:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{amsmath}
\usepackage{xcolor}

%% Following package not needed with newer binaries \usepackage{expl3}% \cs_to_str:N

\ExplSyntaxOn %% https://tex.stackexchange.com/a/100543/4301 \newcommand{\CsToStr}[1]{\cs_to_str:N #1}% \ExplSyntaxOff

\csdef{Bracket Meaning \CsToStr{\lvert}}{Left |} \csdef{Bracket Meaning \CsToStr{\rvert}}{Right |} \csdef{Bracket Meaning \CsToStr{(}}{open (}% FAILS !! \csdef{Bracket Meaning \CsToStr{)}}{close )}

\newcommand{\ShowBracketMeaning}[1]{% #1~ \ifcsdef{Bracket Meaning \CsToStr{#1}}{% \csuse{Bracket Meaning \CsToStr{#1}}% }{\text{No Meaning Defined}}% }%

\begin{document} $\ShowBracketMeaning{\lvert}$

$\ShowBracketMeaning{\rvert}$

{\color{red}% $\ShowBracketMeaning{(}$% <---- ????? This should show "open (" }

$\ShowBracketMeaning{)}$ \end{document}

Peter Grill
  • 223,288

2 Answers2

7

If you try

\edef\test{\CsToStr{(}}
\show\test

you'll see that the answer is

> \test=macro:
->.

The \cs_to_str:N function should only be applied to control sequences; otherwise its result is unpredictable (well, it is predictable, but not what you seem to want to get anyway).

Since both \CsToStr{(} and \CsToStr{)} return empty, the second definition involving them overrides the first.

Solution: if you really want that, don't use \CsToStr:

\csdef{Bracket Meaning \CsToStr{\lvert}}{Left |}
\csdef{Bracket Meaning \CsToStr{\rvert}}{Right |}
\csdef{Bracket Meaning (}{open (}
\csdef{Bracket Meaning )}{close )}

On the other hand, you don't need to remove the backslash when you form a control sequence, as long as the backslash is “other”.

\documentclass{article}
\usepackage{amsmath}
\usepackage{xcolor}

\ExplSyntaxOn \NewExpandableDocumentCommand{\TokenToStr}{m}{\token_to_str:N #1}% \NewExpandableDocumentCommand{\csdefinedTF}{mmm} { \cs_if_exist:cTF { #1 } { #2 } { #3 } } \ExplSyntaxOff

\ExpandArgs{c}\newcommand{Bracket Meaning \TokenToStr{\lvert}}{Left |} \ExpandArgs{c}\newcommand{Bracket Meaning \TokenToStr{\rvert}}{Right |} \ExpandArgs{c}\newcommand{Bracket Meaning \TokenToStr{(}}{open (} \ExpandArgs{c}\newcommand{Bracket Meaning \TokenToStr{)}}{close )}

\newcommand{\ShowBracketMeaning}[1]{% #1~ \csdefinedTF{Bracket Meaning \TokenToStr{#1}}{% \UseName{Bracket Meaning \TokenToStr{#1}}% }{\text{No Meaning Defined}}% }

\begin{document}

$\ShowBracketMeaning{\lvert}$

$\ShowBracketMeaning{\rvert}$

$\ShowBracketMeaning{(}$

$\ShowBracketMeaning{)}$

\end{document}

enter image description here

egreg
  • 1,121,712
  • So, is there a \ifControlSequence{} equivalent macro that I can use in \ShowBracketMeaning to determine if I am going to use \csuse{Bracket Meaning \CsToStr{#1}} or \csuse{Bracket Meaning #1} – Peter Grill Feb 02 '23 at 08:33
  • 1
    @PeterGrill I'm not sure what your purpose is, but there's the conditional \token_if_cs:NTF, so you can branch. And I'd avoid mixing expl3 with etoolbox. – egreg Feb 02 '23 at 09:05
  • 1
    @PeterGrill I added a slightly different approach that requires no branching. – egreg Feb 02 '23 at 18:25
  • Works great (not that there was any doubt). Thanks. I assume \UseName is just a \csuse{}? I also found using \detokenize{} yields the desired results, but wondering if there is a problem with that approach. – Peter Grill Feb 02 '23 at 20:16
  • @PeterGrill Yes, \UseName is the kernel version of \csuse. About \detokenize, it's \tl_to_str:n in expl3, for multiple tokens, whereas \token_to_str:N is for a single token. – egreg Feb 02 '23 at 22:42
2

Befor egreg posted the detailed solution, I found that using \detokenize{} instead of relying on \CsToStr{} yields the desired results.

Am posting this to see in case there are any issues that I am not aware of with this approach.

Code:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{amsmath}
\usepackage{xcolor}

\csdef{Bracket Meaning \detokenize{\lvert}}{Left |} \csdef{Bracket Meaning \detokenize{\rvert}}{Right |} \csdef{Bracket Meaning \detokenize{(}}{open (} \csdef{Bracket Meaning \detokenize{)}}{close )}

\newcommand{\ShowBracketMeaning}[1]{% #1~ \ifcsdef{Bracket Meaning \detokenize{#1}}{% \csuse{Bracket Meaning \detokenize{#1}}% }{\text{No Meaning Defined}}% }%

\begin{document} $\ShowBracketMeaning{\lvert}$

$\ShowBracketMeaning{\rvert}$

$\ShowBracketMeaning{(}$

$\ShowBracketMeaning{)}$ \end{document}

Peter Grill
  • 223,288