As Albert Retey says, the issue is that
Subscript[a, i] = 3 x
affects the DownValues
of Subscript
, not any of the values of a
. Subscript
is one of the few system-defined symbols where you can modify its values without unprotecting it first (Derivative
is another). Thus, in order to localize changes to subscripts of a
, you need to use Block
on Subscript
instead of a
. Thus, for your simple use case, you can do:
Subscript[h, i_][x_] := Block[{Subscript},
Subscript[b, i] = 3 x;
Subscript[b, i]]
Now things work as you want:
In[17]:= Subscript[h, 4][3]
Out[17]= 9
In[18]:= Subscript[b, 3]
Out[18]= Subscript[b, 3]
This has the drawback that you lose , because you lose all access to values of Subscript
from outside the Block
. For a somewhat contrived example of what can go wrong, consider:
Subscript[c, 1] = 17;
Subscript[hh, i_][x_] := Block[{Subscript},
Subscript[b, i] = If[OddQ@Subscript[c, 1], 3 x, 4 x];
Subscript[b, i]]
In[23]:= Subscript[hh, 4][17]
Out[23]= 68
In[24]:= OddQ@Subscript[c, 1]
Out[24]= True
This is perhaps not what you wanted to have happen. Now you can go ahead and manipulate things so that Subscript
gets all the DownValues
and SubValues
from outside the Block
, but this is an error-prone and likely inefficient hassle. However, there's an internal function that does exactly what you would want in this case, called Internal
InheritedBlock`:
Subscript[hhh, i_][x_] := Internal`InheritedBlock[{Subscript},
Subscript[b, i] = If[OddQ@Subscript[c, 1], 3 x, 4 x];
Subscript[b, i]]
Now you get the subscripts you want from outside without having to worry about clobbering anything:
In[31]:= Subscript[hhh, 4][17]
Out[31]= 51
In[32]:= Subscript[b, 3]
Out[32]= Subscript[b, 3]