Re: Comando condizionato dai parametri

#39301
Up
0
Down
::

Ciao a tutti,
avrei bisogno di un aiutino per mettere a posto un paio di problemi (uno facile ed un altro un po’ meno) inerenti alla realizzazione di un comando che può ricevere un parametro opzionale e che, a seconda del suo valore, dovrebbe fare una cosa piuttosto che un’altra.

Cerco di spiegarmi meglio con un esempio. Supponiamo di voler creare un comando per associare ad una certa quantità il simbolo della sua valuta; questo si può fare con il codice seguente:

`\documentclass{minimal}

\usepackage{marvosym} % per il simbolo dell'euro
\usepackage[np]{numprint} % per formattare i numeri

\newcommand{\prezzo}[2][\EUR]{\np{#2}~#1}

\begin{document}

Valuta nazionale: \prezzo{30.00}.

Valuta estera: \prezzo[\$]{30.00}.

\end{document}`
Il primo problema è che, purtroppo, vengo a scoprire che nel caso dei dollari americani il simbolo in questione andrebbe posto davanti alla quantità, e non dopo di essa. L’introduzione di un secondo comando risolverebbe il problema…

`\documentclass{minimal}

\usepackage{marvosym} % per il simbolo dell'euro
\usepackage[np]{numprint} % per formattare i numeri

\newcommand{\prezzo}[1]{\np{#1}~\EUR}
\newcommand{\prezzousa}[1]{\$~\np{#1}}

\begin{document}

Valuta nazionale: \prezzo{30.00}.

Valuta estera: \prezzousa{30.00}.

\end{document}`
… ma questa soluzione non mi piace per due ragioni:

  1. può portare potenzialmente alla creazione di un numero enorme di comandi (e se saltano fuori delle ulteriori convenzioni per le sterline? E per i dong? E per i tugrik? Quanti comandi personalizzati bisognerebbe realizzare?);

  2. vorrei conservare la possibilità di parametrizzare i comandi e di «farci qualcosa» a seconda del valore dei parametri.

In pratica, vorrei un unico comando di nome \prezzo che facesse questo:

  1. se non riceve alcun parametro, posiziona il simbolo a destra del valore, inserendo l’euro in modo predefinito;

  2. se invece riceve un parametro opzionale, guarda il suo valore e decide il da farsi in base ad esso. Ad esempio, potrebbe esistere un elenco che dice «dollari americani e canadesi a sinistra» e «euro e lire a destra». Questo comporta sicuramente l’introduzione di un costrutto if all’interno del comando, che però non saprei come implementare.

Il secondo problema è il seguente: il separatore decimale che si usa comunemente per l’euro è la virgola, mentre per i dollari americani si usa il punto. Mi farebbe piacere che il suddetto comando facesse anche un test del tipo «se ricevo come parametro opzionale il dollaro, passo a numprint un’istruzione che imposti il punto come separatore decimale, altrimenti uso la virgola». Poi, una volta capito il gioco, posso costruire io altri rami if che prendano decisioni differenti a seconda degli altri simboli di valuta, oppure estendere l’elenco.

Interessante problema.
`\documentclass{minimal}

\usepackage{marvosym} % per il simbolo dell'euro
\usepackage[np]{numprint} % per formattare i numeri

\makeatletter
\def\DeclareCurrency#1#2#3#4{%
\@namedef{prezzo@#1}{%
\def\prezzo@sym{#2}%
\expandafter\let\expandafter\prezzo@write\csname prezzo@#3\endcsname
\npdecimalsign{#4}%
}%
}
\def\prezzo@direct#1{\np{#1}\,\prezzo@sym}
\def\prezzo@inverse#1{\prezzo@sym\,\np{#1}}
\newcommand{\prezzo}[2][EUR]{{%
\@nameuse{prezzo@#1}%
\prezzo@write{#2}%
}}
\makeatother

\DeclareCurrency{EUR}{\EUR}{direct}{,}
\DeclareCurrency{US}{\$}{inverse}{.}

\begin{document}

\prezzo{30,00}

\prezzo[US]{30,00}

\prezzo[EUR]{30.00}

\end{document}`
La macro \DeclareCurrency ha quattro argomenti: la chiave (arbitraria) corrispondente alla valuta richiesta, il simbolo da usare, una parola chiave (“direct” oppure “inverse”) per stabilire se il simbolo va prima o dopo (con direct va dopo), il separatore della parte decimale.

Questa macro a sua volta ne definisce un’altra il cui scopo è di fare alcune definizioni! Ma alla fine si esegue il comando giusto: \prezzo[EUR]{30,00} chiama (in un gruppo) \prezzo@EUR che dà le opportune definizioni
– \def\prezzo@sym{\EUR}
– \let\prezzo@write=\prezzo@direct
– \npdecimalsign{,}
Quindi viene eseguito \prezzo@write sull’argomento obbligatorio di \prezzo; il valore di default dell’argomento opzionale è EUR, quindi \prezzo{30.00} fa la stessa cosa.

Con \prezzo[US]{30,00}, invece, viene chiamato \prezzo@US che definisce
– \def\prezzo@sym{\S}
– \let\prezzo@write=\prezzo@inverse
– \npdecimalsign{.}
e poi esegue \prezzo@write sull’argomento di \prezzo.

Niente \if; TeX ha gli (le?) “associative arrays” tramite \csname…\endcsname; \@namedef e \@nameuse sono i comandi LaTeX per accedere alla costruzione. Con la macro “ombrello” \DeclareCurrency puoi estendere il meccanismo a quante valute ti piaccia.

Ciao
Enrico

Go to top