1

I'm trying to define a macro returning a calculated length, but making the parameter optional breaks the macro (error Missing number, treated as zero.):

\documentclass{article}

\usepackage{xfp}
\usepackage{numprint}

\newcommand{\testa}[1]{\fpeval{#1*0.03}\linewidth}
\newcommand{\testb}[1][1]{\fpeval{#1*0.03}\linewidth}

\begin{document}

\lenprint[pt]{\testa{1}}% prints 10,34958 pt

\lenprint[pt]{\testa{2}}% prints 20,69915 pt

\lenprint[pt]{\testb}% gives ERROR and prints 0.030 pt

\lenprint[pt]{\testb[2]}% gives ERROR and prints 0.060 pt

\end{document}

Can you help understand why?

Is there a way to make the parameter optional without breaking the working macro?

N.B. The above MWE uses \lenprint, but I'm asking for a solution working in general or at least with \addtolength, since my real world need is to use the macro as argument of \addtolength.

3
  • A command with an optional argument is not fully expandable, a required feature if you want to use it in the argument to \lenprint.
    – egreg
    Jun 25, 2021 at 8:31
  • @egreg Is there a way to make the parameter optional without breaking the working macro?
    – mmj
    Jun 25, 2021 at 8:37
  • Very short answer: no.
    – egreg
    Jun 25, 2021 at 8:39

1 Answer 1

1

You can define \testb as expandable macro. For example:

\long\def\testb#1{\ifx[#1\afterfi{\testbA[}\else\afterfi{\testbA[1]#1}\fi}
\def\testbA[#1]{\fpeval{#1*0.03}\linewidth}
\long\def\afterfi#1#2\fi{\fi#1}

It will not work in all cases but your case works:

\lenprint[pt]{\testb}% works

\lenprint[pt]{\testb[2]}% works
2
  • Just by chance; \lenprint does \setlength{\@tempdima}{#2} and so you get \@tempdima=\testb\relax which works because there is a token after \testb that can be taken as the argument. But it's very specific and other usages of \testb will definitely break.
    – egreg
    Jun 25, 2021 at 12:29
  • And it works also for my real world need which is using the macro as argument of \addtolenght, so thanks.
    – mmj
    Jun 25, 2021 at 18:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.