0

I am using variables of the form $a[i]$, e.g. $(a[1],a[2],a[3],...)$. When I pass them to a function I need to determine which one they are, in other words, what the value of $i$ is.

Specifically, I need to do something like this:

a[1]=2.1; a[2]=3.5;
Test[x_]:=Block[{i}, *Some how set i=index value of a[i]*;
Return[{i,a[i]}];
];

So that

Test[a[1]]

returns

{1,2.1}

and

Test[a[2]]

returns

{2,3.5}
Phillip Dukes
  • 938
  • 5
  • 18
  • 2
    We may need more context to answer this. Simplistically you could use pattern matching, e.g. fn[a[n_]] := Row@{"this one is ", n}. Somehow I think that you might mean something else however. Perhaps you are having evaluation problems, e.g. there is an existing definition like a[1] = 3.2? – Mr.Wizard Aug 01 '16 at 00:10
  • Are you going to be applying this directly to a[1] or a[2]? If so SetAttributes[Test, HoldAll]; Test[a[i_]] := i would work. But it won't work in all applications. E.g. var = a[2]; Test[var]. – Michael E2 Aug 01 '16 at 00:29
  • How is this useful? How are you going to use it? Seems like {i, a[i]} is shorter than Test[a[i]]. – Michael E2 Aug 01 '16 at 00:58
  • Thanks for the Accept. I am curious, which part of my answer did you find useful? If it is the first then I would like to join Michael in asking how you are going to use this. It may be that you would be better served by keeping a and the index (1 or 2) separate to begin with. In fact this is one of the major advantages of using "indexed objects" like this, e.g. (32202). You might define your Test function something like Test[s_Symbol, i_] := {i, s[i]} then call it with Test[a, 1]. This does not require any Hold attributes. – Mr.Wizard Aug 01 '16 at 01:21
  • You could also use a SubValues definition like test[s_Symbol][i_] := {i, s[i]} which would allow test[a] /@ {1, 2}. Finally please consider not starting user function names with capital letters as there is risk of collision with built-ins, either now or in a future version. – Mr.Wizard Aug 01 '16 at 01:24
  • @Mr.Wizard I have developed several lists of data, e.g. x[i][[j,k]], for which the index i has significance. To process the data in needed to know the value of i. I know I could have entered the same data as x[[i,j,k]] but that seemed too ugly to me. So, having already entered it as x[i][[j,k]] I needed your help. – Phillip Dukes Aug 02 '16 at 01:48

1 Answers1

5

Typically you need a Hold Attribute on your Test function and to pass the "symbol" unevaluated:

a[1] = 2.1; a[2] = 3.5;

SetAttributes[Test, HoldFirst]

Test[x : _[n_]] := Block[{i}, i = n; {i, x}]   (* Block is superfluous here *)

Test[a[1]]
Test[a[2]]
{1, 2.1}

{2, 3.5}

This will not let you do something like Test /@ {a[1], a[2]} however as e.g. a[1] will first evaluate to 2.1 and there is nothing to match.

If you cannot pass the argument unevaluated you have a bit of a problem. I strongly suggest you rethink the design of your program in that case. However in an effort to be helpful you could attempt a reverse look-up in the DownValues of a, assuming you somehow "know" the Symbol name a.

test2[v_, s_Symbol] :=
 Cases[DownValues[s], (_[s[n_]] :> v) :> {n, v}]

test2[#, a] & /@ {2.1, 3.5}
{{{1, 2.1}}, {{2, 3.5}}}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371