2

I am trying to define some new commands to be able to define default values for some of the things I will be using over and over again in order to centralize where the style and the typical letter used should be defined.

The things that I have so far and that gives some trouble is the following

\newcommand{\Prob}[1]{% \IfEqCase{#1}{% {1}{p}% {2}{q}% {3}{r}% }[#1]% }% \newcommand{\RandomVar}[1]{% \IfEqCase{#1}{% {1}{X}% {2}{Y}% {3}{Z}% }[#1]% }% 

And an example of use is

$p_{\RandomVar1, \RandomVar2}$, $\Prob{p_{\RandomVar1,\RandomVar2}}$ 

The goal of all this is to be able to have default values for probability distributions, default values for random variables, and to also be able to provide a different value than the default ones if needed. Here the first code works and produces $p_{X,Y}$, the second one doesn't and produce the following error

I've run across a `}' that doesn't seem to match anything. For example, `\def\a#1{...}' and `\a}' would produce this error. 

I think that the problem is similar to that of this post but I couldn't work around a solution, I tried putting braces around things without really understanding what I was doing. Any help would be welcome.


Complete example

\documentclass{article} \usepackage{xstring} \newcommand{\Prob}[1]{% \IfEqCase{#1}{% {1}{p}% {2}{q}% {3}{r}% }[#1]% }% \newcommand{\RandomVar}[1]{% \IfEqCase{#1}{% {1}{X}% {2}{Y}% {3}{Z}% }[#1]% }% \begin{document} $\Prob1$, $\Prob2$, $\Prob{p_{X,Y}}$, $p_{\RandomVar1, \RandomVar2}$ $\Prob{p_{\RandomVar1,\RandomVar2}}$ \end{document} 

The first line of the document yields

$p$, $q$, $p_{X,Y}$, $p_{X,Y}$ 

The last line should yield

$p_{X,Y}$ 

but instead gives an error.

10
  • 3
    always show a small but complete example. Don't let people guess or search which packages you use. Commented Dec 7, 2022 at 18:18
  • Sorry, but it isn't clear what you're expecting. You're passing \Prob the argument p_{\RandomVar{1},\Randomvar{2}} which is definitely not 1, 2 or 3. But there are other problems with xstring (which are the cause of the error). Commented Dec 7, 2022 at 18:25
  • @UlrikeFischer Sorry about that, please find it included at the end of the post. Commented Dec 7, 2022 at 18:33
  • @egreg Maybe the full code helps, so basically if 1,2,3 is provided it should give the associated value, otherwise it should give the given argument. Commented Dec 7, 2022 at 18:34
  • @P.Quinton But you never pass 1, 2 or 3 to \Prob. Commented Dec 7, 2022 at 18:45

3 Answers 3

2

Seems making commands robust by defining via \NewDocumentCommand instead of \newcommand does the trick.

\documentclass{article} %\usepackage{xparse} \usepackage{xstring} \NewDocumentCommand{\Prob}{m}{% \IfEqCase{#1}{% {1}{p}% {2}{q}% {3}{r}% }[{#1}]% }% \NewDocumentCommand{\RandomVar}{m}{% \IfEqCase{#1}{% {1}{X}% {2}{Y}% {3}{Z}% }[{#1}]% }% \begin{document} $\Prob1$, $\Prob2$, $\Prob{p_{X,Y}}$, $p_{\RandomVar1, \RandomVar2}$ $\Prob{p_{\RandomVar1,\RandomVar2}}$ \end{document} 

The last line yields p_{\RandomVar1,\RandomVar2} which in turn yields p_{X,Y}.

enter image description here


A better approach might be using expandable \str_case:nnTF:

\documentclass{article} \ExplSyntaxOn \cs_new:Npn \Prob #1 {% % \exp_args:Ne fully expands the argument passed to \str_case:nnTF. \exp_args:Ne \str_case:nnTF {#1} { {1} {p} {2} {q} {3} {r} } {} {#1} } \cs_new:Npn \RandomVar #1 {% % \exp_args:Ne fully expands the argument passed to \str_case:nnTF. \exp_args:Ne \str_case:nnTF {#1} { {1} {X} {2} {Y} {3} {Z} } {} {#1} } \ExplSyntaxOff \begin{document} $\Prob1$, $\Prob2$, $\Prob{p_{X,Y}}$, $p_{\RandomVar1, \RandomVar2}$ $\Prob{p_{\RandomVar1,\RandomVar2}}$ \end{document} 

enter image description here

2
  • Thank you very much for your answer. Commented Dec 8, 2022 at 8:23
  • @P.Quinton egreg's answer is better than mine as 1) it uses \str_case:nnF instead of \str_case:nnTF 2) it provides abstraction. In order to do a favor to those who might in future encounter this question while searching for answers I suggest unaccepting my answer and accepting egreg's. Commented Dec 8, 2022 at 15:41
3

You can define your \Prob and \RandomVar very simply using expandable TeX primitive \ifcase:

\def\Prob #1{\ifcase 0#1\or p\or q\or r\fi} \def\RandomVar #1{\ifcase 0#1\or X\or Y\or Z\fi} 
1
  • Thank you for your answer, it looks nice but I turned out to accept the other one because of the minimal amount of things I had to change. Commented Dec 8, 2022 at 8:23
3

The problem is in how xstring processes its commands, using full expansion unless explicitly told otherwise.

This is the cause of failure of \Prob{p_{\RandomVar{1},\RandomVar{2}}}, because xstring tries to fully expand \RandomVar{1} which cannot survive \edef.

The \str_case:nnF function in expl3 hasn't this problem. Since you seem to want to define several commands in a similar fashion (return from a list of choices when the argument fits, or return the full argument), abstraction seems useful.

\documentclass{article} \ExplSyntaxOn \NewDocumentCommand{\definechoicemacro}{mm} {% #1 = macro name, #2 = choices \NewDocumentCommand{#1}{m} { \str_case:nnF { ##1 } { #2 } { ##1 } } } \ExplSyntaxOff \definechoicemacro{\Prob}{ {1}{p} {2}{q} {3}{r} } \definechoicemacro{\RandomVar}{ {1}{X} {2}{Y} {3}{Z} } \begin{document} $\Prob1$, $\Prob2$, $\Prob{p_{X,Y}}$, $p_{\RandomVar1, \RandomVar2}$ $\Prob{p_{\RandomVar1,\RandomVar2}}$ \end{document} 

enter image description here

If you prefer to define the macros individually,

\documentclass{article} \ExplSyntaxOn \cs_new_eq:NN \choosefromordefault \str_case:nnF \ExplSyntaxOff \newcommand{\Prob}[1]{% \choosefromordefault{#1}{ {1}{p} {2}{q} {3}{r} }{#1}% } \newcommand{\RandomVar}[1]{% \choosefromordefault{#1}{% {1}{X} {2}{Y} {3}{Z} }{#1}% } \begin{document} $\Prob1$, $\Prob2$, $\Prob{p_{X,Y}}$, $p_{\RandomVar1, \RandomVar2}$ $\Prob{p_{\RandomVar1,\RandomVar2}}$ \end{document} 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.