1

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}
asked Oct 24 at 17:36
8
  • 1
    as always in expl3, given However, \fp_set_variable:nn doesn't seem to expand #1 you could use (or declare if necessary) an \fp_set_variable:en that does expand #1 Commented Oct 24 at 18:07
  • 1
    you can use l3regex to do the replacement in combination with the variant @DavidCarlisle mentioned. or use \exp_args:N.... Commented Oct 24 at 18:12
  • 1
    I don't think you should delete your question. but I think it would be better to start from one of the answers which does what you want and ask e.g. whether the syntax can be modified in whichever way you need. your question did not say why you didn't want to use the expandable answers, so it just seemed weird to be asking how to change my answer to do what the other answers already gave you. Commented Oct 25 at 7:16
  • @cfr yes. You're right. Now I restore it if I could find it. Commented Oct 25 at 7:22
  • 1
    @cfr yes, I have solved that. Commented Oct 25 at 16:24

3 Answers 3

2

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}

output

answered Oct 24 at 19:09
3
  • 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} } . Commented Oct 25 at 7:41
  • @xcn NO, it’s not possible, because variables cannot have names containing nonletters. Commented Oct 25 at 8:57
  • it’s possible if change your answer a little. Commented Oct 26 at 4:17
4

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.

answered Oct 24 at 19:42
2
  • How to use Optex? I can't find Optex Compiler in Texworks editor. Commented Oct 26 at 3:49
  • 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). Commented Oct 26 at 15:52
0

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}
answered Oct 26 at 4:23

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.