I know that \fp_new_variable:n ⟨identifier⟩ must consist entirely of Latin letters from [a-zA-Z]. In the \setvar command below, I want to replace any numbers or underscores in the parameter #1 before using it, for example, convert h_2 to hUnderscoreTwo, and then let \fp_set_variable uses it. However, \fp_set_variable:nn doesn't seem to expand #1. Is there any way to achieve this?
\documentclass[12pt]{article}
\ExplSyntaxOn
\seq_new:N \g__xcn_var_list_seq
\NewDocumentCommand{\setvar}{mm}
{
\seq_if_in:NnF \g__xcn_var_list_seq {#1 }
{
\fp_new_variable:n {#1}
\seq_gput_left:Nn \g__xcn_var_list_seq {#1}
}
\fp_set_variable:nn {#1} {#2}
}
\NewExpandableDocumentCommand{\usevar}{O{15}m}
{
\fp_eval:n { round( #2 , #1 ) }
}
\ExplSyntaxOff
\begin{document}
\setvar{h}{600 * 2}
\usevar{h}
%\setvar{h_2}{600 * 2} \usevar{h_2}
\end{document}
3 Answers 3
You can do it by associating to the "external" name a "purified" internal one. But this will be much slower, mind you.
\documentclass[12pt]{article}
\ExplSyntaxOn
\prop_new:N \g__xcn_var_list_prop
\tl_new:N \l__xcn_var_purified_tl
\NewDocumentCommand{\setvar}{mm}
{
\__xcn_var_purify:n {#1}
\prop_if_in:NnF \g__xcn_var_list_prop {#1 }
{
\exp_args:NV \fp_new_variable:n \l__xcn_var_purified_tl
\prop_gput:NnV \g__xcn_var_list_prop {#1} \l__xcn_var_purified_tl
}
\exp_args:NV \fp_set_variable:nn \l__xcn_var_purified_tl {#2}
}
\NewExpandableDocumentCommand{\usevar}{O{15}m}
{
\fp_eval:n { round( \prop_item:Nn \g__xcn_var_list_prop {#2} , #1 ) }
}
\cs_new_protected:Nn \__xcn_var_purify:n
{
\tl_set:Nn \l__xcn_var_purified_tl {#1}
\exp_args:NNe \tl_replace_all:Nnn \l__xcn_var_purified_tl
{ \char_generate:nn { `_ } {8} } % underscore
{ underscore }
\regex_replace_all:nnN { ([0-9]+) } { \c{int_to_roman:n} {1円} } \l__xcn_var_purified_tl
\tl_set:Ne \l__xcn_var_purified_tl { \l__xcn_var_purified_tl }
}
\ExplSyntaxOff
\begin{document}
\setvar{h}{600 * 2}
\usevar{h}
\setvar{h_2}{600 * 2} \usevar{h_2}
\setvar{h_2}{2*pi} \usevar{h_2}
\fpeval{\usevar{h_2}/2}
\end{document}
-
Can the syntax be modified so that I can use variable directly? such as use
\setvar{h_c}{600 * 2 + h_b}instead if\setvar{h_c}{600 * 2 + \usevar{h_b} }.xcn– xcn2025年10月25日 07:41:02 +00:00Commented 2 days ago -
@xcn NO, it’s not possible, because variables cannot have names containing nonletters.egreg– egreg2025年10月25日 08:57:31 +00:00Commented 2 days ago
-
it’s possible if change your answer a little.xcn– xcn2025年10月26日 04:17:26 +00:00Commented yesterday
In OpTeX, we can use \expr macro:
\mathinexpr
\def\_decdigits{15}
\def\setvar#1#2{\directlua{#1 = #2}}
\def\usevar#1{\nnum{\expr{#1}}}
\setvar{h}{600 * 2}
\usevar{h}
\setvar{h_2}{600 * 2} \usevar{h_2}
\setvar{h_2}{2*pi} \usevar{h_2}
\usevar{h_2/2}
\bye
The result is the same as in the egreg's answer.
-
How to use Optex? I can't find Optex Compiler in Texworks editor.xcn– xcn2025年10月26日 03:49:08 +00:00Commented yesterday
-
I don't know what Texworks editor is. If you are unable to find OpTeX in the editor menu then it is problem of this editor. TeXlive and MikTeX include OpTeX (you can use command line with optex command).wipet– wipet2025年10月26日 15:52:48 +00:00Commented 21 hours ago
This modified answer allows to use understore in argument #2 of \setvar command.
\documentclass[12pt]{article}
\ExplSyntaxOn
\prop_new:N \g__xcn_var_list_prop
\tl_new:N \l__xcn_var_purified_tl
\tl_new:N \l__xcn_var_purifiedeq_tl
\NewDocumentCommand{\setvar}{mm}
{
\__xcn_var_purify:n {#1}
\prop_if_in:NnF \g__xcn_var_list_prop {#1 }
{
\exp_args:NV \fp_new_variable:n \l__xcn_var_purified_tl
\prop_gput:NnV \g__xcn_var_list_prop {#1} \l__xcn_var_purified_tl
}
\tl_set_eq:NN \l__xcn_var_purifiedeq_tl \l__xcn_var_purified_tl
\__xcn_var_purify:n {#2}
\exp_args:NV \fp_set_variable:nn \l__xcn_var_purifiedeq_tl \l__xcn_var_purified_tl
}
\NewExpandableDocumentCommand{\usevar}{O{15}m}
{
\fp_eval:n { round( \prop_item:Nn \g__xcn_var_list_prop {#2} , #1 ) }
}
\cs_new_protected:Nn \__xcn_var_purify:n
{
\tl_set:Nn \l__xcn_var_purified_tl {#1}
\exp_args:NNe \tl_replace_all:Nnn \l__xcn_var_purified_tl
{ \char_generate:nn { `_ } {8} } % underscore
{ U }
%\regex_replace_all:nnN { ([0-9]+) } { \c{int_to_roman:n} {1円} } \l__xcn_var_purified_tl
\tl_set:Ne \l__xcn_var_purified_tl { \l__xcn_var_purified_tl }
}
\ExplSyntaxOff
\begin{document}
\setvar{h_a}{600 * 2}
\usevar{h_a}
\fpeval{\usevar{h_a}/2}
\setvar{h_b}{3.14+h_a}
\usevar{h_b}
\end{document}
However, \fp_set_variable:nn doesn't seem to expand #1you could use (or declare if necessary) an\fp_set_variable:enthat does expand#1l3regexto do the replacement in combination with the variant @DavidCarlisle mentioned. or use\exp_args:N....