# How to parse optional arguments without keyval?

The current implementation only supports rounding with the specified digits in the optional arguments.

\documentclass{beamer}
\usepackage{multido}
\usepackage{pstricks}
\usepackage[nomessages]{fp}

% \pstVerb concatenator

% Constant declarator invoked in the preamble
\newcommand\const[3][]{%
\if\relax\detokenize{#1}\relax
\edef\temporary{#3}%
\else
\edef\temporary{round(#3:#1)}%
\fi
\expandafter\FPeval\csname#2\expandafter\endcsname
\expandafter{\expandafter{\temporary}}%

\makeatletter
\def\pst@@picture@i[#1]#2(#3,#4){%
% BEGIN - redefine \const for invocation inside pspicture
\renewcommand\const[3][]{%
\if\relax\detokenize{##1}\relax
\edef\temporary{##3}%
\else
\edef\temporary{round(##3:##1)}%
\fi
\expandafter\FPeval\csname##2\expandafter\endcsname
\expandafter{\expandafter{\temporary}}%
\pstVerb{/##2 \csname##2\endcsname\space def}\ignorespaces}%
% END - redefine \const for invocation inside pspicture
\@ifnextchar(% ignore anything between [] and ()
% BEGIN - inject \LoadConstants into pspicture
% END - inject \LoadConstants into pspicture
}
\makeatother

\usepackage[active,tightpage]{preview}
\PreviewEnvironment{pspicture}
\PreviewBorder=25pt\relax

\SpecialCoor
\const{Side}{root(2,17)}% the square root of 17

\begin{document}
\begin{frame}
\begin{pspicture}(\Side,\Side)
\psframe(!Side dup)\pause
\multido{\i=0+30}{12}{%
\const[5]{temp}{cos(\i*pi/180)}
\rput{\i}(!Side 2 div dup dup \i\space PtoC 3 1 roll add 3 1 roll add){$\temp$}\pause
}
\end{pspicture}
\end{frame}
\end{document}

## Objective:

I want to make \const behave as follows. If we invoke

• \const[4,r]{...}{...}, it will use round with 4 digits after .
• \const[4,t]{...}{...}, it will use trunc with 4 digits after .
• \const[c]{...}{...}, it will use clip to trim all trailing zeros

Any idea to improve the code is welcome!

-
What will happen if the input is \const[3]{...}{...} –  Marco Daniel Apr 27 '13 at 11:02
@MarcoDaniel: It is not allowed. –  Please don't touch Apr 27 '13 at 11:14
Then you want two optional arguments. If you use pstricks you already have available a key-value syntax; why not exploiting it? –  egreg Apr 27 '13 at 12:54
@egreg: I have not learnt it yet. :-) –  Please don't touch Apr 27 '13 at 12:55

\def\zzA#1,#2#3\relax#4{
\if t#2 trunc(#4:#1)%
\else\if r#2 round(#4:#1)%
\else clip(#4)%
\fi\fi}

% Constant declarator invoked in the preamble
\newcommand\const[3][]{%
\if\relax\detokenize{#1}\relax
\edef\temporary{#3}%
\else
\edef\temporary{\zzA#1,c\relax{#3}}%
\wlog{::\temporary}%
\fi
\expandafter\FPeval\csname#2\expandafter\endcsname
\expandafter{\expandafter{\temporary}}%

produces a log of

::  trunc(root(2,17):4)
::  round(root(2,17):4)
:: clip(root(2,17))

from

\const{Side}{root(2,17)}% the square root of 17
\const[4,t]{Side}{root(2,17)}% the square root of 17
\const[4,r]{Side}{root(2,17)}% the square root of 17
\const[c]{Side}{root(2,17)}% the square root of 17
-
+1 I am trying to apply it. –  Please don't touch Apr 27 '13 at 11:27
What is #3 for in \zzA? –  Please don't touch Apr 27 '13 at 11:40
What does \const[4]{Side}{root(2,17)} do? It should throw an error. –  Please don't touch Apr 27 '13 at 16:03
@Bugbusters errors are tricky as I'm inside the edef, so currently it checks for r and t and then teh \else clause for clip picks up everything else. You could test for clip explicitly and then have an else clause that did unknwnfunction(..) so that would then generate an error later but I'm not sure taht is better, as it would error in the Postscript rather than tex. –  David Carlisle Apr 27 '13 at 16:19
Error should be in TeX such that it automatically stops the next compilation with GhostScript. –  Please don't touch Apr 27 '13 at 16:31
\documentclass{minimal}
\parindent=0pt
\usepackage{pstricks}
\usepackage[nomessages]{fp}

\makeatletter
\def\const{\@ifnextchar[\const@i{\const@i[r]}}
\def\const@i[#1]{\expandafter\const@ii#1,,\@nil}
\def\const@ii#1,#2,#3\@nil#4#5{%
\if\relax\detokenize{#2}\relax
\if\relax\detokenize{#1}\relax \expandafter\const@iii\expandafter{#5}{#4}%
\else
\pst@isnum{#1}%
{>>> Wrong Parameter '#1' \@namedef{#4}{}}
{\ifx#1c \expandafter\const@iii\expandafter{clip(#5)}{#4}%
\else   \expandafter\const@iii\expandafter{#5}{#4}%
\fi}%
\fi%
\else%
\ifx#2t  \expandafter\const@iii\expandafter{trunc(#5:#1)}{#4}%
\else
\ifx#2c\expandafter\const@iii\expandafter{clip(#5}{#4}%
\else  \expandafter\const@iii\expandafter{round(#5:#1)}{#4}%
\fi%
\fi%
\fi%
}
\def\const@iii#1#2{%
\expandafter\FPeval\csname#2\expandafter\endcsname\expandafter{\expandafter{#1}}%
\makeatother

\begin{document}
\const{Side}{root(2,17)} \Side \\
\const[c]{Side}{root(2,17)} \Side \\
\const[4]{Side}{root(2,17)} \Side \\
\const[r]{Side}{root(2,17)} \Side\\
\const[6,r]{Side}{root(2,17)} \Side\\
\const[6,t]{Side}{root(2,17)} \Side
\end{document}

An empty argument like \const[]{... is also possible.

And here the same with the key/value syntax:

\documentclass{minimal}
\parindent=0pt
\usepackage{pstricks}
\usepackage[nomessages]{fp}

\makeatletter
\define@key[psset]{}{Roundtype}[round]{\expandafter\pst@@Roundtype#1\@nil}%
\def\pst@@Roundtype#1#2\@nil{%
\ifx#1t \def\psk@Roundtype{trunc}%
\else\ifx#1c \def\psk@Roundtype{clip}\else\def\psk@Roundtype{round}%
\fi\fi}
\define@key[psset]{}{Decimals}[-1]{\pst@getint{#1}\psk@Decimals}%
\psset{Roundtype,Decimals}
\def\pst@RT@c{clip}

\def\const{\def\pst@par{}\pst@object{const}}
\def\const@i#1#2{%
\use@par%
\ifx\psk@Roundtype\pst@RT@c
\expandafter\const@ii\expandafter{clip(#2)}{#1}
\else
\ifnum\psk@Decimals<1\relax
\expandafter\const@ii\expandafter{#2}{#1}%
\else
\expandafter\const@ii\expandafter{\psk@Roundtype(#2:\psk@Decimals)}{#1}%
\fi%
\fi%
}

\def\const@ii#1#2{%
\expandafter\FPeval\csname#2\expandafter\endcsname\expandafter{\expandafter{#1}}%
\makeatother

\begin{document}
\const{Side}{root(2,17)} \Side \\
\const[Roundtype=c]{Side}{root(2,17)} \Side \\
\const[Decimals=4]{Side}{root(2,17)} \Side \\
\const[Roundtype=r]{Side}{root(2,17)} \Side\\
\const[Decimals=6,Roundtype=r]{Side}{root(2,17)} \Side\\
\const[Decimals=6,Roundtype=t]{Side}{root(2,17)} \Side\\
\const[]{Side}{root(2,17)} \Side
\end{document}

-
Could you make the compilation in TeX phase terminated with an error message when invoking \const[4]{Side}{root(2,17)}? –  Please don't touch Apr 27 '13 at 13:18
\@pstrickserr{Invalid argument!}\@ehpb –  Herbert Apr 27 '13 at 13:35
The key/value version behaves strange, for example: (1) \const{}{} should produce 18 digits after period. (2) \const[Roundtype=c,Decimals=4] does not make sense. –  Please don't touch Apr 27 '13 at 13:42
then set the default to 18 digits. Where is the ptoblem?? I have no idea what makes sense or not. I do not use the fp package for that! –  Herbert Apr 27 '13 at 13:56
How to set the default to 18? I don't think it is possible because it will throw an error. Only 17 is the max when using trunc and round. –  Please don't touch Apr 27 '13 at 15:11