4

I have a macros.tex included in the preamble that creates some useful dumb macros. I want to define a macro for writing fractions that adds a brace if the argument is longer than 1 character, what I have so far is:

\usepackage{xstrings}
\newcommand{\fracdivide}[3]{%
    \StrLen{#2}[\arglen]%
    \ifthenelse{\arglen > 1}
    {%
        \frac{#1\left(#2\right)}{#1#3}
    }%
    {%
        \frac{#1#2}{#1#3}
    }%
}

That produces the following error: !Incomplete \iffalse; all text was ignored after line 16.

line 16 is exactly the line where I have the \StrLen command. If I remove it (for example using 2 instead of \arglen), it compiles correctly.

Why do I get this error? And how do I solve it?

Here's a MWE, it seems related to the \text command of amsmath.

\documentclass{minimal}
\usepackage{mathtools}
\usepackage{xstring}
\usepackage{ifthen}
\newcommand{\vect}[1]{\boldsymbol{\mathbf{#1}}}
\newcommand{\fracdivide}[3]{%
    \StrLen{#2}[\arglen]%
    \ifthenelse{\arglen > 1}
    {%
        \frac{#1\left(#2\right)}{#1#3}
    }%
    {%
        \frac{#1#2}{#1#3}
    }%
}
\newcommand{\partialdd}[2]{\fracdivide{\partial}{#1}{#2}}
\newcommand{\ddt}[1]{\partialdd{#1}{t}}

\begin{document}
$\ddt{f^\text{big}}$
\end{document}
4
  • 1
    Make a complete example. One can't run tests with snippets. Commented Jun 9, 2017 at 17:03
  • I tried a couple of examples, but got no failure.
    – egreg
    Commented Jun 9, 2017 at 17:11
  • My best guess is something that's not fully-expandable is being passed as the second argument to \fracdivide. Possibly some other command from xstrings, but I've never used that package before.
    – TH.
    Commented Jun 9, 2017 at 17:14
  • @UlrikeFischer you are right. I'm sorry. I uploaded a MWE.
    – rdbisme
    Commented Jun 9, 2017 at 18:28

3 Answers 3

3

You are better using \noexpandargs:

\documentclass{article}
\usepackage{mathtools}
\usepackage{xstring}
\usepackage{ifthen}
\newcommand{\vect}[1]{\boldsymbol{\mathbf{#1}}}
\newcommand{\fracdivide}[3]{%
  \begingroup\noexpandarg
  \StrLen{#2}[\arglen]%
  \ifthenelse{\arglen > 1}
    {%
     \frac{#1(#2)}{#1#3}%
    }%
    {%
     \frac{#1#2}{#1#3}%
    }%
  \endgroup
}
\newcommand{\partialdd}[2]{\fracdivide{\partial}{#1}{#2}}
\newcommand{\ddt}[1]{\partialdd{#1}{t}}

\begin{document}

\[
\ddt{f^{\mathrm{big}}} + \ddt{\Gamma}
\]

\end{document}

enter image description here

Note: I removed the useless (and harmful) \left and \right.

The problem is that commands such as \mathrm or \text won't survive the full expansion performed by default by \StrLen. With \noexpandargs this is avoided.

However, something like \ddt{\vect{x}} will be parenthesized. I don't think this is a really useful macro.

Probably a macro with a *-version is easier to work with.

\documentclass{article}
\usepackage{mathtools}
\usepackage{xparse}

\NewDocumentCommand{\fracdivide}{smmm}{%
  \frac{#2\IfBooleanTF{#1}{(#3)}{#3}}{#2#4}%
}

\NewDocumentCommand{\partialdd}{smm}{%
  \IfBooleanTF{#1}{\fracdivide*}{\fracdivide}{\partial}{#2}{#3}%
}
\NewDocumentCommand{\ddt}{sm}{%
  \IfBooleanTF{#1}{\partialdd*}{\partialdd}{#2}{t}%
}

\newcommand{\vect}[1]{\boldsymbol{\mathbf{#1}}}

\begin{document}

\[
\ddt*{f^{\mathrm{big}}} + \ddt{f_1}
- \ddt{\vect{x}} + \ddt*{\vect{x}+\vect{y}}
\]

\end{document}

enter image description here

3
  • Thanks for your effort! In fact I just realized that it puts braces in the situation you mention. Is there a way to strip all the "operators" acting on a argument to retrieve the actual length of the argument so that \vect{x} results in length of 1? Or also \hat{\vect{x}}?
    – rdbisme
    Commented Jun 9, 2017 at 20:59
  • @SolidSnake Not really, I'm afraid. Much better to specify yourself whether you want parentheses or not.
    – egreg
    Commented Jun 9, 2017 at 21:56
  • It's actually a dumb macro. :). I edited the question accordingly. And thanks for your help.
    – rdbisme
    Commented Jun 9, 2017 at 21:58
1

Your attempt at extracting the length of the string requires the argument to expand to a string. However, f^\text{big} does not. We can \detokenize the input:

\documentclass{article}

\usepackage{mathtools,xstring}

\newcommand{\fracdivide}[3]{
    \StrLen{\detokenize{#2}}[\arglen]
    \ifnum\arglen>1
      \frac{#1\left(#2\right)}{#1#3}
    \else
      \frac{#1#2}{#1#3}
    \fi
}
\newcommand{\partialdd}[2]{\fracdivide{\partial}{#1}{#2}}
\newcommand{\ddt}[1]{\partialdd{#1}{t}}

\begin{document}
$\ddt{f^\text{big}}$
\end{document}
2
  • 1
    This way \fracdivide{d}{\alpha}{x} will choose the parenthesized branch.
    – egreg
    Commented Jun 9, 2017 at 20:35
  • @egreg: Yes. Hopefully an edge case.
    – Werner
    Commented Jun 9, 2017 at 20:54
1

You need something like this:

\def\ddt#1{{\partial\maybebraces{#1}\over\partial t}}
\def\maybebraces#1{\maybebracesA#1&}
\def\maybebracesA#1#2&{\ifx&#2&#1\else\left(#1#2\right)\fi}


$$\ddt{f^{\rm big}} + \ddt{\Gamma}$$

\bye

In contrast to the other solutions here we do not mix the problem of construction of the fraction (with "partial" sign and with "t" in denominator) with the problem of "maybebraces". And (of course) no special packages (and no LaTeX) is explicitly needed.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .