0
$\begingroup$

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}
$\endgroup$
  • 2
    $\begingroup$ 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? $\endgroup$ – Mr.Wizard Aug 1 '16 at 0:10
  • $\begingroup$ 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]. $\endgroup$ – Michael E2 Aug 1 '16 at 0:29
  • $\begingroup$ How is this useful? How are you going to use it? Seems like {i, a[i]} is shorter than Test[a[i]]. $\endgroup$ – Michael E2 Aug 1 '16 at 0:58
  • $\begingroup$ 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. $\endgroup$ – Mr.Wizard Aug 1 '16 at 1:21
  • $\begingroup$ 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. $\endgroup$ – Mr.Wizard Aug 1 '16 at 1:24
5
$\begingroup$

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}}}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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