Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

In order to separate the content structure from the style, I decided to implement commands for denoting random variables:

\newcommand{\myrv}[1]{\mathbf{#1}}
\newcommand{\rvA}{\myrv{A}}
\newcommand{\rvB}{\myrv{B}}
\newcommand{\rvC}{\myrv{C}}
...

This way, if I ever decide to change the style of random variables from \mathbf to say \mathbb, all I need to do is to change the definition of \myrv. Is a way to generate the commands \rvA, \rvB, \rvC, ... automatically?

share|improve this question
    
What do you mean by automatically? Generate the commands when they needed? One way could be the useage of \csgdef from the etoolbox package. –  Christian Hupfer Apr 24 at 12:34
1  
Is tex.stackexchange.com/questions/25452/… what you’re looking for? –  doncherry Apr 24 at 12:36
    
@doncherry The linked question deals with part of this one, but it might be useful to explain how to create whole "batches" of commands with a loop or some such: again etoolbox helps. –  Paul Stanley Apr 24 at 12:42
1  

3 Answers 3

up vote 5 down vote accepted

There are other similar questions, but none that treats explicitly this problem, as far as I can see.

\documentclass{article}

\makeatletter
\newcommand{\generate}[4]{%
  %#1 = prefix, #2 = macro, #3 = starting point, #4 = end point
  \def\@tempa{#1} % we don't want to lowercase it
  \count@=`#3
  \loop
  \begingroup\lccode`?=\count@
  \lowercase{\endgroup\@namedef{\@tempa ?}{#2{?}}}%
  \ifnum\count@<`#4
  \advance\count@\@ne
  \repeat
}

\generate{rv}{\mathbf}{A}{Z}
\show\rvA
\show\rvZ
\generate{rv}{\mathbf}{a}{z}
\show\rva
\show\rvz

The \show command are just to see that it worked. The terminal output is

> \rvA=macro:
->\mathbf {A}.
l.17 \show\rvA

? 
> \rvZ=macro:
->\mathbf {Z}.
l.18 \show\rvZ

? 
> \rva=macro:
->\mathbf {a}.
l.20 \show\rva

? 
> \rvb=macro:
->\mathbf {b}.
l.21 \show\rvb

An extended version using expl3:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\generate}{ m m m }
 {
  \group_begin:
  \keys_set:nn { iliketocode/generate } { #3 }
  \iliketocode_generate:nn { #1 } { #2 }
  \group_end:
 }

\keys_define:nn { iliketocode/generate }
 {
  prefix .tl_set:N = \l_iliketocode_generate_prefix_tl,
  suffix .tl_set:N = \l_iliketocode_generate_suffix_tl,
  wrapper .tl_set:N = \l_iliketocode_generate_wrapper_tl,
 }

\cs_new_protected:Npn \iliketocode_generate:nn #1 #2
 {
  \int_step_inline:nnnn { `#1 } { 1 } { `#2 }
   {
    \group_begin:
    \char_set_lccode:nn { `? } { ##1 }
    \tl_to_lowercase:n
     {
      \cs_gset:cpx { \l_iliketocode_generate_prefix_tl ? \l_iliketocode_generate_suffix_tl }
       {
        \exp_not:V \l_iliketocode_generate_wrapper_tl { ? }
       }
     }
    \group_end:
   }
 }
\ExplSyntaxOff

\generate{A}{Z}{prefix=rv,wrapper=\mathbf}
\show\rvA
\show\rvZ
\generate{a}{z}{prefix=rv,wrapper=\mathbf}
\show\rva
\show\rvz
\generate{A}{Z}{suffix=cal,wrapper=\mathcal}
\show\Acal
\show\Zcal

The syntax of \generate is a bit different: the first argument is the starting point, the second argument is the end point; the third argument is a key-value list; the keys are

prefix
suffix
wrapper

and the example should make their meanings clear. Not specifying a wrapper is allowed, but this would just make an alias for the single letter; prefix and suffix can also be specified together.

Here's the output on the terminal, just for checking.

> \rvA=\long macro:
->\mathbf {A}.
l.39 \show\rvA

? 
> \rvZ=\long macro:
->\mathbf {Z}.
l.40 \show\rvZ

? 
> \rva=\long macro:
->\mathbf {a}.
l.42 \show\rva

? 
> \rvz=\long macro:
->\mathbf {z}.
l.43 \show\rvz

? 
> \Acal=\long macro:
->\mathcal {A}.
l.45 \show\Acal

? 
> \Zcal=\long macro:
->\mathcal {Z}.
l.46 \show\Zcal
share|improve this answer

You could define a macro that takes a list of names and creates the corresponding macros:

\documentclass{article}

\newcommand{\myrv}[1]{\mathbf{#1}}

\makeatletter
\newcommand*\defrvar[1]{
  \expandafter\newcommand\csname rv#1\endcsname[1][]{\myrv{#1}}}

\newcommand*\defrvars[1]{
  \@for\@i:=#1\do{\expandafter\defrvar\expandafter{\@i}}}
\makeatother


\defrvars{a,b,c} % this defines \rva, \rvb and \rvc

\begin{document}

Hi $\rva, \rvb + \rvc$
\end{document}
share|improve this answer
\newcommand{\myrv}[1]{\mathbf{#1}}
\newcommand{\makerv}[1]{%
  \expandafter\newcommand\csname rv#1\endcsname{\myrv{#1}}%
}

\newcommand{\defAllRv}[1]{%
  \ifx#1\deffAllRv%
  \else%
      \makerv{#1}\expandafter\mydefallb%
  \fi}
\deffAllRv abcdefghijklmnopqrstuvwxyz\defAllRv

this code define all \rva...\rvz. it's basend on : Difference between \if and \ifx and Defining a newcommand, with variable name, inside another newcommand

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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