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

I have the following code:

Subscript[f, i_][x_] := Block[{a},
  Subscript[a, i] = 3 x;
  Subscript[a, 1]
]

If I evaluate for example Subscript[f,1][2], it evaluates to 6. After that asking what Subscript[a,1] is also gives me six. However, I want a to be a local variable.

My question: how can I define a local variable while using indices...?

Note: the original post mentioned that evaluating Subscript[f,1][2] = 6 would lead to the described behaviour, which just isn't true. A reasonable guess is that this was ment to mean that Subscript[f,1][2] was to be evaluated and it would evaluate to 6 (which it does). After that Subscript[a,1] will evaluate to 6 as reported.

share|improve this question

migrated from math.stackexchange.com Apr 5 '12 at 15:30

This question came from our site for people studying math at any level and professionals in related fields.

    
Hello Bee, and welcome to math.SE. I think your question is better suited to the mathematica.SE site, so I'm going to migrate it there. There will be a link that appears below the question here that you can follow to the new location of your question. If you need help associating an account on mathematica.SE, you can flag your question for moderator attention, and someone over there will help out. –  Zev Chonoles Apr 5 '12 at 15:29
    
I can't seem to reproduce this. Does this behave this way on a fresh Mathematica session? –  rcollyer Apr 5 '12 at 15:39
    
@Bee: are you following this and the discussion to one of the answers? I'd suggest you have a look at my edit to your question and see if you think this makes sense. –  Albert Retey Apr 5 '12 at 16:44
    
@AlbertRetey Bee is unregistered on Mathematics, and not at all here. So, it is likely that she is not following this. Do as you will, then. –  rcollyer Apr 5 '12 at 16:51

3 Answers 3

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 InternalInheritedBlock`:

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]
share|improve this answer

The problem is that the definition which makes Subscript[a,i] evaluate to 6 is stored in the DownValues of Subscript. The down values of Subscript don't care about the blocking of a and will still exist when Block exits. You can check that by evaluating DownValues[Subscript]. You could use TagSet (shortcut: /:) to store that value in the UpValues of the localized a, which would behave as you expect (i.e. the rule in UpValues of a is removed when Block exits):

ClearAll[f, a, Subscript]
Subscript[f, i_][x_] := Block[{a},
  a /: Subscript[a, i] = 3 x;
  Subscript[a, 1]
]

on the other hand I wouldn't actually recommend to use such subscripted variables, what you have seen is probably only one of several unexpected things that could happen.

Side Note:It probably should be mentioned that the definition for Subscript[f,i_][x_] is also not associated with f but with Subscript, which can be checked by evaluating SubValues[Subscript]. Unfortunately this can not be changed by using TagSet for f, since Mathematica here will complain about f being too deep in the left hand side expression. One possibility to change that is to reformulate the function definition to e.g.:

f /: Subscript[f, i_] = Function[x,
  Block[{a},
   a /: Subscript[a, i] = 3 x;
   Subscript[a, 1]
   ]
  ]

which will behave the same as the original in most practical cases but of course is not exactly the same thing. You can use UpValues[f] to check that this rule is now really associated with f.

share|improve this answer
    
Actually, DownValues[Subscript] does not show anything, however SubValues[Subscript] does. –  rcollyer Apr 5 '12 at 16:39
    
I think that depends on whether one evaluates Subscript[f,1][2] or Subscript[f,1][2]=6, as discussed elswhere... –  Albert Retey Apr 5 '12 at 16:54
    
Ah, I see. Then the answer needs to be clarified slightly, as there are no DownValues of Subscript associated with f (which is what I think you're answer implies) only SubValues, but there DownValues associated with a. –  rcollyer Apr 5 '12 at 17:06
1  
@rcollyer: I just added some additional remarks about downvalues, upvalues and subvalues. Hope this is now somewhat clearer. –  Albert Retey Apr 6 '12 at 13:26
    
You already had my +1, but thanks. –  rcollyer Apr 6 '12 at 14:05

I think you want to use Module[] instead of Block[]

Subscript[f, i_][x_] := Module[{a}, Subscript[a, i] = 3 x; Subscript[a, 1]]
share|improve this answer
    
Absolutely, but can you get the behavior with Subscript[a,1] that the OP is observing? –  rcollyer Apr 5 '12 at 15:42
    
@rcollyer: Yes of course, it's even what I would expect :-). What are you observing and why would you think it should be different from what the OP writes? –  Albert Retey Apr 5 '12 at 15:48
    
Yes, if I post the OP's code into a fresh MMA session, I reproduce his issue, Subscript[a,1] returns 6 after an evaluation of Subscript[f,1][2]. However, changing Block[] to Module[], restarting the kernal and running the notebook again yields the desired behavior, namely Subscript[f,1][2] = 6 and Subscript[a,1] = Subscript[a,1] –  johntfoster Apr 5 '12 at 15:48
1  
@johntfoster: while that in a sense behaves like the OP wants, you would accumulate one rule per call to Subscript[f,_][_] in the downvalues of Subscript (evaluate DownValues[Subscript] to see what I'm talking about). This might not be a problem but could well become one when the function gets called frequently. Also there might be reasons to use Block instead of Module, they serve different purposes... –  Albert Retey Apr 5 '12 at 15:52
1  
@rcollyer: I have now edited the question and made a note about that change. –  Albert Retey Apr 5 '12 at 16:43

Your Answer

 
discard

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