Skip to main content
Extended answer to cover variation requested by the OP
Source Link
m_goldberg
  • 108.1k
  • 16
  • 104
  • 259

I take a somewhat different approach to defining a function to make subscripted variables in of the requested form. The algorithm doesn't differ substantially from the one used by Rod Lm; the difference lies in the way I use multiple function definitions, pattern matching, and destructuring of the formal argument sequences.

SetAttributes[fancySubscript, HoldFirst]
fancySubscript[var_Symbol, tag_String, index_Integer] /; 
    Not[ValueQ[var]] :=
  Subscript[var, tag <> ToString[index]]
fancySubscript[var_Symbol, tags : {_String ..}, index_Integer] /; 
    Not[ValueQ[var]] :=
  fancySubscript[var, #, index] & /@ tags
fancySubscript[var_Symbol, tags : {_String ..}, 
   indices : {_Integer ..}] /; Not[ValueQ[var]] :=
  fancySubscript[var, tags, #] & /@ indices

The condition Not[ValueQ[var] ensures that fancySubscript doesn't accept variables having values.

a = 42; fancySubscript[a, "tag", 2]

fancySubscript[a, "tag", 2]

The overloaded definitions ensure that fancySubscript accepts all the following forms:

fancySubscript[b, "tag", 2]

$b_{\text{tag2}}$

fancySubscript[b, {"foo", "bar", "baz"}, 2]

$\left\{b_{\text{foo2}},b_{\text{bar2}},b_{\text{baz2}}\right\}$

fancySubscript[b, {"foo", "bar", "baz"}, Range@3]

$\left( \begin{array}{ccc} b_{\text{foo1}} & b_{\text{bar1}} & b_{\text{baz1}} \\ b_{\text{foo2}} & b_{\text{bar2}} & b_{\text{baz2}} \\ b_{\text{foo3}} & b_{\text{bar3}} & b_{\text{baz3}} \\ \end{array} \right)$

###Edit

To answer the question raised in a comment by Alex, it is easy to change fancySubscript to do double indexing, rather than concatenating the tags and indices. The only modification required is to redefine the first definition of fancySubscript as

fancySubscript[var_Symbol, tag_String, index_Integer] /; 
    Not[ValueQ[var]] := 
  Subscript[var, tag, index]

With this change, for example,

fancySubscript[b, {"foo", "bar", "baz"}, 2]

gives

$\left\{b_{\text{foo},2},b_{\text{bar},2},b_{\text{baz},2}\right\}$

I take a somewhat different approach to defining a function to make subscripted variables in of the requested form. The algorithm doesn't differ substantially from the one used by Rod Lm; the difference lies in the way I use multiple function definitions, pattern matching, and destructuring of the formal argument sequences.

SetAttributes[fancySubscript, HoldFirst]
fancySubscript[var_Symbol, tag_String, index_Integer] /; 
    Not[ValueQ[var]] :=
  Subscript[var, tag <> ToString[index]]
fancySubscript[var_Symbol, tags : {_String ..}, index_Integer] /; 
    Not[ValueQ[var]] :=
  fancySubscript[var, #, index] & /@ tags
fancySubscript[var_Symbol, tags : {_String ..}, 
   indices : {_Integer ..}] /; Not[ValueQ[var]] :=
  fancySubscript[var, tags, #] & /@ indices

The condition Not[ValueQ[var] ensures that fancySubscript doesn't accept variables having values.

a = 42; fancySubscript[a, "tag", 2]

fancySubscript[a, "tag", 2]

The overloaded definitions ensure that fancySubscript accepts all the following forms:

fancySubscript[b, "tag", 2]

$b_{\text{tag2}}$

fancySubscript[b, {"foo", "bar", "baz"}, 2]

$\left\{b_{\text{foo2}},b_{\text{bar2}},b_{\text{baz2}}\right\}$

fancySubscript[b, {"foo", "bar", "baz"}, Range@3]

$\left( \begin{array}{ccc} b_{\text{foo1}} & b_{\text{bar1}} & b_{\text{baz1}} \\ b_{\text{foo2}} & b_{\text{bar2}} & b_{\text{baz2}} \\ b_{\text{foo3}} & b_{\text{bar3}} & b_{\text{baz3}} \\ \end{array} \right)$

I take a somewhat different approach to defining a function to make subscripted variables in of the requested form. The algorithm doesn't differ substantially from the one used by Rod Lm; the difference lies in the way I use multiple function definitions, pattern matching, and destructuring of the formal argument sequences.

SetAttributes[fancySubscript, HoldFirst]
fancySubscript[var_Symbol, tag_String, index_Integer] /; 
    Not[ValueQ[var]] :=
  Subscript[var, tag <> ToString[index]]
fancySubscript[var_Symbol, tags : {_String ..}, index_Integer] /; 
    Not[ValueQ[var]] :=
  fancySubscript[var, #, index] & /@ tags
fancySubscript[var_Symbol, tags : {_String ..}, 
   indices : {_Integer ..}] /; Not[ValueQ[var]] :=
  fancySubscript[var, tags, #] & /@ indices

The condition Not[ValueQ[var] ensures that fancySubscript doesn't accept variables having values.

a = 42; fancySubscript[a, "tag", 2]

fancySubscript[a, "tag", 2]

The overloaded definitions ensure that fancySubscript accepts all the following forms:

fancySubscript[b, "tag", 2]

$b_{\text{tag2}}$

fancySubscript[b, {"foo", "bar", "baz"}, 2]

$\left\{b_{\text{foo2}},b_{\text{bar2}},b_{\text{baz2}}\right\}$

fancySubscript[b, {"foo", "bar", "baz"}, Range@3]

$\left( \begin{array}{ccc} b_{\text{foo1}} & b_{\text{bar1}} & b_{\text{baz1}} \\ b_{\text{foo2}} & b_{\text{bar2}} & b_{\text{baz2}} \\ b_{\text{foo3}} & b_{\text{bar3}} & b_{\text{baz3}} \\ \end{array} \right)$

###Edit

To answer the question raised in a comment by Alex, it is easy to change fancySubscript to do double indexing, rather than concatenating the tags and indices. The only modification required is to redefine the first definition of fancySubscript as

fancySubscript[var_Symbol, tag_String, index_Integer] /; 
    Not[ValueQ[var]] := 
  Subscript[var, tag, index]

With this change, for example,

fancySubscript[b, {"foo", "bar", "baz"}, 2]

gives

$\left\{b_{\text{foo},2},b_{\text{bar},2},b_{\text{baz},2}\right\}$

Source Link
m_goldberg
  • 108.1k
  • 16
  • 104
  • 259

I take a somewhat different approach to defining a function to make subscripted variables in of the requested form. The algorithm doesn't differ substantially from the one used by Rod Lm; the difference lies in the way I use multiple function definitions, pattern matching, and destructuring of the formal argument sequences.

SetAttributes[fancySubscript, HoldFirst]
fancySubscript[var_Symbol, tag_String, index_Integer] /; 
    Not[ValueQ[var]] :=
  Subscript[var, tag <> ToString[index]]
fancySubscript[var_Symbol, tags : {_String ..}, index_Integer] /; 
    Not[ValueQ[var]] :=
  fancySubscript[var, #, index] & /@ tags
fancySubscript[var_Symbol, tags : {_String ..}, 
   indices : {_Integer ..}] /; Not[ValueQ[var]] :=
  fancySubscript[var, tags, #] & /@ indices

The condition Not[ValueQ[var] ensures that fancySubscript doesn't accept variables having values.

a = 42; fancySubscript[a, "tag", 2]

fancySubscript[a, "tag", 2]

The overloaded definitions ensure that fancySubscript accepts all the following forms:

fancySubscript[b, "tag", 2]

$b_{\text{tag2}}$

fancySubscript[b, {"foo", "bar", "baz"}, 2]

$\left\{b_{\text{foo2}},b_{\text{bar2}},b_{\text{baz2}}\right\}$

fancySubscript[b, {"foo", "bar", "baz"}, Range@3]

$\left( \begin{array}{ccc} b_{\text{foo1}} & b_{\text{bar1}} & b_{\text{baz1}} \\ b_{\text{foo2}} & b_{\text{bar2}} & b_{\text{baz2}} \\ b_{\text{foo3}} & b_{\text{bar3}} & b_{\text{baz3}} \\ \end{array} \right)$