Another scenario where expandability is useful is creating external text-files, e.g., comma-separated-value-lists/.csv-files holding contents of databases, that are to be processed by programs other than TeX which don't understand LaTeX sytax so that all control sequence tokens in the stuff to be written to external text file should go away via expansion.
The following example produces two .csv-files via the package datatool.
(The command \verbatiminput
from the package verbatim is used so that you can see the content of these files within the pdf-file which results from compiling.)
The second of these files comes from entries where the non-expandable command is used, thus it contains things like \myDimensionCommand {2}{2.54cm}
which you probably don't want in a .csv-file that is to be processed further by software other than LaTeX.
\documentclass{article}
\usepackage{datatool, verbatim}
% \ExplSyntaxOn
% \cs_new_eq:NN \fpeval \fp_eval:n
% \cs_new_eq:NN \dimeval \dim_eval:n
% \ExplSyntaxOff
\NewExpandableDocumentCommand {\convertto} {omm}
{%%
% #1 = number of decimal digits
% #2 = length
% #3 = new unit
\IfNoValueTF {#1}
{%%
\fpeval{\dimeval{#2}/(1#3)}\,#3%%
}
{%%
\fpeval{round(\dimeval{#2}/(1#3),#1)}\,#3%%
}%%
}
% Define a command that uses \convertto
\NewDocumentCommand{\myDimensionCommand}{m m}
{%% The first argument of \convertto is optional and therefore
%% must be in square brackets!!!
The converted dimension is: \convertto[{#1}]{#2}{mm}.%%
}
% Create .csv-files holding values of length quantities
% expressed as multiples of different units:
\begingroup
\def\,{}% \convertto beneath other things delivers a
% control symbol token \, , which in turn in LaTeX
% is defined as a protected/an unexpandable command
% for producing a thin horizontal space (.16667em).
% We want neither a thinspace nor the control sequence
% \, to be written to text files, thus within a local
% scope/a group redefine \, so that it just vanishes
% when being expanded.
\DTLnewdb{Database}%
\DTLaddcolumn{Database}{ValueToConvert}%
\DTLsetheader{Database}{ValueToConvert}{dimension to convert}%
\DTLaddcolumn{Database}{ConversionResults}%
\DTLsetheader{Database}{ConversionResults}{result of conversion}%
\dtlexpandnewvalue
\DTLnewrow{Database}%
\DTLnewdbentry{Database}{ValueToConvert}{2.54cm}%
\DTLnewdbentry{Database}{ConversionResults}{\convertto[2]{2.54cm}{in}}%
\DTLnewrow{Database}%
\DTLnewdbentry{Database}{ValueToConvert}{65536sp}%
\DTLnewdbentry{Database}{ConversionResults}{\convertto[2]{65536sp}{pt}}%
\dtlnoexpandnewvalue
\DTLsavedb{Database}{Entriesxpanded.csv}%
\DTLcleardb{Database}%
\DTLaddcolumn{Database}{ValueToConvert}%
\DTLsetheader{Database}{ValueToConvert}{dimension to convert}%
\DTLaddcolumn{Database}{ConversionResults}%
\DTLsetheader{Database}{ConversionResults}{result of conversion}%
\dtlexpandnewvalue
\DTLnewrow{Database}%
\DTLnewdbentry{Database}{ValueToConvert}{2.54cm}%
\DTLnewdbentry{Database}{ConversionResults}{\myDimensionCommand{2}{2.54cm}}%
\DTLnewrow{Database}%
\DTLnewdbentry{Database}{ValueToConvert}{72bp}%
\DTLnewdbentry{Database}{ConversionResults}{\myDimensionCommand{2}{72bp}}%
\dtlnoexpandnewvalue
\DTLsavedb{Database}{Entriesunexpanded.csv}%
\DTLcleardb{Database}%
\endgroup
\begin{document}
% The content of the .csv-files
Here is the content of the file "Entriesxpanded.csv" which holds entries coming from expandable commands:
\verbatiminput{Entriesxpanded.csv}
Here is the content of the file "Entriesunexpanded.csv" which holds entries coming from unexpandable commands:
\verbatiminput{Entriesunexpanded.csv}
\end{document}
\myDimensionCommand
and doesn't rely on\convertto
being (fully) expandable. Please provide an example that actually rests on expandability.\romannumeral
-expansion or\expanded
, can be implemented in a way where you know exactly the amount of expansion steps needed for obtaining the result This is very useful when implementing routines which re-arrange tokens to form arguments for other routines. This also is very useful when implementing routines which call other routines or instances of themselves as "sub-processes" and where you need to know exactly when the result of the "sub-process" is there.\convertto
is optional an must be in square brackets[...]
but it seems that with the call to\convertto
coded into the definition of\myDimensionCommand
that argument is in curly braces{...}
which won't work out as expected.\rule{\convertto[2]{34pt}{cm}}
gives me a missing number.\rule
is:\rule[raise-height]{width}{thickness}
. As width you give\convertto[2]{34pt}{cm}
, but do you also give a thickness? And the definition of\convertto
contains\,
, which is not a valid token when specifying TeX <dimension> quantities like width/thickness. E.g.,{\def\,{}\rule{\convertto[2]{34pt}{cm}}{\convertto[2]{34pt}{cm}}}
yields a nice square.