3

How can I set variable definition as a global variable to use it outside the eachfor loop?

\newcommand\Var[3]{ 
 \expandafter\edef\csname #1\Roman{#2}\endcsname{#3}
 }
\newcounter{count}
\foreach \i in {1,2,3,4,5,6,7,8,9}{
\stepcounter{count}
\Var{var}{count}{\Alph{count}}
}

\varII ???

  • \expandafter\xdef\csname #1\Roman{#2}\endcsname{#3}, i.e. \xdef instead of \edef. It is, however, not necessarily a good idea to make variables global. – Schrödinger's cat Feb 12 at 6:34
  • You could just use \documentclass{article} \newcommand\Var[3]{ \expandafter\edef\csname #1\Roman{#2}\endcsname{#3} } \newcounter{count} \setcounter{count}{0} \loop \stepcounter{count} \Var{var}{count}{\Alph{count}}% \ifnum\value{count}<10 \repeat \begin{document} \varIII \end{document} – Schrödinger's cat Feb 12 at 6:39
  • The \i of the \foreach-loop is never used. Seems instead of iterating on the comma-list 1,2,3,4,5,6,7,8,9 for obtaining an amount of nine iterations, one could as well implement a loop where keeping track of the amount of iterations is done by counting/incrementing. – Ulrich Diez Feb 12 at 16:43
2

Welcome! The answer to your question is: use \xdef instead of \edef, i.e.

\documentclass{article}
\usepackage{pgffor}
\newcounter{count}
\newcommand\Var[3]{ 
 \expandafter\xdef\csname #1\Roman{#2}\endcsname{#3}
 }
\foreach \i in {1,2,3,4,5,6,7,8,9}{
\stepcounter{count}
\Var{var}{count}{\Alph{count}}
}
\begin{document}
\varIII
\end{document}

However, you do not need to make the variable global. Rather, you can use the built-in \loop for that.

\documentclass{article}
\newcommand\Var[3]{ 
 \expandafter\edef\csname #1\Roman{#2}\endcsname{#3}
 }
\newcounter{count}
\setcounter{count}{0}
\loop
\stepcounter{count}
\Var{var}{count}{\Alph{count}}%
\ifnum\value{count}<10
\repeat
\begin{document}
\varIII
\end{document}
| improve this answer | |
  • thx for ur reply, but I had tried xdef and it didn't work as ! Undefined control sequence. Further I want to use eachfor loop for another complicated loop and it just is a simple example. – Hadi Entezari Feb 12 at 6:56
  • @HadiEntezari I posted a full code, which works. – Schrödinger's cat Feb 12 at 6:59
  • thx for ur kindness, the point was calling the right package. – Hadi Entezari Feb 12 at 7:22
1

You can do it with xparse; I assume your values are not consecutive integers. I added an optional number to change the list separator in case you need commas in the values.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\setvariables}{mO{,}m}
 {% #1 = prefix for the variable name
  % #2 = separator (optional, default comma)
  % #3 list of values
  \hadi_setvariables:nnn { #1 } { #2 } { #3 }
 }

\cs_new_protected:Nn \hadi_setvariables:nnn
 {
  \seq_set_split:Nnn \l_tmpa_seq { #2 } { #3 }
  \seq_indexed_map_inline:Nn \l_tmpa_seq
   {% ##1 is the current index, ##2 is the current item
    \tl_set:cn { #1 \int_to_Roman:n { ##1 } } { ##2 }
   }
 }

\ExplSyntaxOff

\begin{document}

\setvariables{var}{1,2,3,9,5.2}

\varI \quad \varII \quad \varIII \quad \varIV \quad \varV

\setvariables{xyz}[;]{1;0.1;a,b}

\xyzI \quad \xyzII \quad \xyzIII

\end{document}

enter image description here

| improve this answer | |
0

With pgffor's/TikZ's \foreach each iteration takes place within its own local scope. Non-global assignments (e.g., in terms of \edef) which take place within an iteration are restricted to that iteration's local scope.

Be aware that when using the LaTeX 2ε-kernel's \@for instead of pgffor's/TikZ's \foreach, iterations do not take place within a new local scope. Therefore with the LaTeX 2ε-kernel's \@for you don't need \xdef but can use \edef—can be something like this:

\documentclass{article}

\makeatletter
\newcounter{count}
\newcommand\Var[3]{%
  \expandafter\edef\csname #1\Roman{#2}\endcsname{#3}%
}%
\setcounter{count}{0}%
\@for\i:=0001,0010,0011,0100,0101,0110,0111,1000,1001\do{%
  \stepcounter{count}%
  \Var{var}{count}{Alphabetic: \Alph{count}--Binary: \i}%
}%
\makeatother

\begin{document}
\noindent
\verb|\varI|: \varI \\
\verb|\varII|: \varII \\
\verb|\varIII|: \varIII \\
\verb|\varIV|: \varIV \\
\verb|\varV|: \varV \\
\verb|\varVI|: \varVI \\
\verb|\varVII|: \varVII \\
\verb|\varVIII|: \varVIII \\
\verb|\varIX|: \varIX \\
\end{document}

enter image description here


You use \Roman{⟨LaTeX counter⟩} and \Alph{⟨LaTeX counter⟩}.

If you instead use \@Roman{⟨TeX number quantity⟩} and \@Alph{⟨TeX number quantity⟩}, you can do without count-registers.

In case ε-TeX-extensions are not available you may need to implement a routine for expandable incrementing:

\documentclass{article}

\makeatletter
%------------------------------------------------------------------------------
% Expandable incrementing of natural number formed by a sequence of
% explicit catcode-12-character-tokens-from-the-set {0,1,2,3,4,5,6,7,8,9}
%..............................................................................
% \Increment{<natural number k as sequence of explicit catcode-12-character-
%             tokens from the set 0123456789>}
% ->
% <natural number (k+1) as sequence of explicit catcode-12-character-tokens
%  from the set 0123456789>
% In expansion-contexts the result is delivered after two expansion-steps/is 
% obtained by "hitting" \Increment with \expandafter twice.
%------------------------------------------------------------------------------
\newcommand\Increment[1]{%
  \romannumeral0%
  \UD@IncrementReverse{\UD@IncrementFork{}}{\relax}{}#1\relax
}%
\newcommand\UD@IncrementReverse[4]{%
  \ifx\relax#4%
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {#1#3#2}{\UD@IncrementReverse{#1}{#2}{#4#3}}%
}%
\@ifdefinable\UD@IncrementSelect{%
  \long\def\UD@IncrementSelect#10123456789\relax#2#3!!{#2}%
}%
\newcommand\UD@IncrementFork[2]{%
  \UD@IncrementSelect
  #2123456789\relax{\UD@IncrementReverse{ }{}{}#11}%
  0#223456789\relax{\UD@IncrementReverse{ }{}{}#12}%
  01#23456789\relax{\UD@IncrementReverse{ }{}{}#13}%
  012#2456789\relax{\UD@IncrementReverse{ }{}{}#14}%
  0123#256789\relax{\UD@IncrementReverse{ }{}{}#15}%
  01234#26789\relax{\UD@IncrementReverse{ }{}{}#16}%
  012345#2789\relax{\UD@IncrementReverse{ }{}{}#17}%
  0123456#289\relax{\UD@IncrementReverse{ }{}{}#18}%
  01234567#29\relax{\UD@IncrementReverse{ }{}{}#19}%
  012345678#2\relax{\UD@IncrementFork{#10}}%
  0123456789#2{\UD@IncrementReverse{ }{}{}#11\relax}%
  0123456789\relax{\UD@IncrementReverse{ }{}{}#11#2}%
  !!%
}%
%------------------------------------------------------------------------------
\newcommand\VarLoop[4]{%
  \ifnum#2<\expandafter\@firstofone\expandafter{\number#1} %
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi{%
    \expandafter\edef\csname#3\@Roman{#1}\endcsname{#4{#1}}%
    %\expandafter\show\csname#3\@Roman{#1}\endcsname%
    \expandafter\expandafter\expandafter\VarLoop
    \expandafter\expandafter\expandafter{\Increment{#1}}{#2}{#3}{#4}%
  }%
}%
%------------------------------------------------------------------------------
\VarLoop{1}{9}{var}{\@Alph}
%------------------------------------------------------------------------------    
\makeatother

\begin{document}
\noindent
\verb|\varI|: \varI \\
\verb|\varII|: \varII \\
\verb|\varIII|: \varIII \\
\verb|\varIV|: \varIV \\
\verb|\varV|: \varV \\
\verb|\varVI|: \varVI \\
\verb|\varVII|: \varVII \\
\verb|\varVIII|: \varVIII \\
\verb|\varIX|: \varIX \\
\end{document}

enter image description here

In case ε-TeX-extensions are available you can use \number\numexpr...\relax for expandable incrementing:

\documentclass{article}

\makeatletter
%------------------------------------------------------------------------------
\newcommand\VarLoop[4]{%
  \ifnum#2<\expandafter\@firstofone\expandafter{\number#1} %
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi{%
    \expandafter\edef\csname#3\@Roman{#1}\endcsname{#4{#1}}%
    %\expandafter\show\csname#3\@Roman{#1}\endcsname%
    \expandafter\VarLoop
    \expandafter{\number\numexpr\number#1+1\relax}{#2}{#3}{#4}%
  }%
}%
%------------------------------------------------------------------------------
\VarLoop{1}{9}{var}{\@Alph}
%------------------------------------------------------------------------------    
\makeatother

\begin{document}
\noindent
\verb|\varI|: \varI \\
\verb|\varII|: \varII \\
\verb|\varIII|: \varIII \\
\verb|\varIV|: \varIV \\
\verb|\varV|: \varV \\
\verb|\varVI|: \varVI \\
\verb|\varVII|: \varVII \\
\verb|\varVIII|: \varVIII \\
\verb|\varIX|: \varIX \\
\end{document}

enter image description here


By the way:

Seems you use \Roman for converting digits into character-tokens of category code 11 (letter) which can occur in names of control word tokens like \varI, \varII, etc.

Did you know that via \csname..\endcsname you can have (La)TeX construct tokens whose names contain digits?

E.g.,

\csname varI\endcsname yields the control-word-token \varI.

In the same way

\csname var1\endcsname yields the control-word-token \var1.

You cannot type \var1 directly in .tex-input-files as the reading-and-tokenizing-apparatus of (La)TeX would tokenize as \varcontrol word token and 1explicit character token of category code 12(other).

But \csname var1\endcsname is read and tokenized as follows:

  1. \csnamecontrol word token
  2. vexplicit character token of category code 11(letter)
  3. aexplicit character token of category code 11(letter)
  4. rexplicit character token of category code 11(letter)
  5. 1explicit character token of category code 12(other)
  6. \endcsnamecontrol word token

In the next stage, at the time of expanding things, the tokens that form the \csname..\endcsname-expression get expanded and the result of expanding \csname... is the token \var1control word token.

There is this nice special feature in (La)TeX, called #{-notation which lets you define macros whose last argument is delimited by {.

You can define a command

\name⟨stuff without braces⟩{⟨ControlSequenceName⟩}

which (after two expansion-steps) yields:

⟨stuff without braces⟩\ControlSequenceName

You can use it like:

\name{Var23}\Var23
\name\newcommand{Var23}...\newcommand\Var23...
\name\global\long\def{Var23}...\global\long\def\Var23...
\name\show{Var23}\show\Var23
\name\meaning{Var23}\meaning\Var23
\name\name\let{Var23}={Var24}\name\let\Var23={Var24}\let\Var23=\Var24

\documentclass{article}

\newcounter{scratchcounter}

% Let's define the \name-macro:

\makeatletter
\newcommand\exchange[2]{#2#1}%
\@ifdefinable\name{\long\def\name#1#{\romannumeral0\innername{#1}}}%
\newcommand\innername[2]{\expandafter\exchange\expandafter{\csname#2\endcsname}{ #1}}%
\makeatother

% Let's define "variables/macros" \var1..\var9 in a loop:

\setcounter{scratchcounter}{0}%
\loop
  \stepcounter{scratchcounter}%
  \name\name{@ifdefinable}{var\number\value{scratchcounter}}{%
    \name\edef{var\number\value{scratchcounter}}{\Alph{scratchcounter}}%
  }%
\ifnum\value{scratchcounter}<9
\repeat

% Let's define the macro \foo45/c-;/bar

\name\newcommand*{foo45/c-;/bar}{This is a macro with a weird name.}

\parindent=0ex

\begin{document}
\verb|\name{var1}|: $\to$ \texttt{\name\string{var1}} $\to$ \name{var1} \\
\verb|\name{var2}|: $\to$ \texttt{\name\string{var2}} $\to$ \name{var2} \\
\verb|\name{var3}|: $\to$ \texttt{\name\string{var3}} $\to$ \name{var3} \\
\verb|\name{var4}|: $\to$ \texttt{\name\string{var4}} $\to$ \name{var4} \\
\verb|\name{var5}|: $\to$ \texttt{\name\string{var5}} $\to$ \name{var5} \\
\verb|\name{var6}|: $\to$ \texttt{\name\string{var6}} $\to$ \name{var6} \\
\verb|\name{var7}|: $\to$ \texttt{\name\string{var7}} $\to$ \name{var7} \\
\verb|\name{var8}|: $\to$ \texttt{\name\string{var8}} $\to$ \name{var8} \\
\verb|\name{var9}|: $\to$ \texttt{\name\string{var9}} $\to$ \name{var9} \\
\verb|\name{foo45/c-;/bar}|: $\to$ \texttt{\name\string{foo45/c-;/bar}}  $\to$ \name{foo45/c-;/bar}

\hrulefill\null

Now let's redefine \verb|\var8|:

\verb|\name\renewcommand{var8}[1]{Now we have a macro which processes an argument: #1}|\\
$\to$\\
\verb|\renewcommand\var8[1]{Now we have a macro which processes an argument: #1}|\\
\name\renewcommand{var8}[1]{Now we have a macro which processes an argument: #1}

\verb|\name\string{var8}: \name\meaning{var8}| yields:

\begingroup
\ttfamily\frenchspacing
\hbox{%
\name\string{var8}: \name\meaning{var8}%
}%
\endgroup
\end{document}

enter image description here

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.