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.
ClearAll@foo;
foo[tag_] := (
   tag /: tag[i_] := tag[[i]]
   );
a = {7, 8, 9};
foo[a];
a[2]

I wanted the above to output 8, but encountered an error:

TagSetDelayed::sym: "Argument {7,8,9} at position 1 is expected to be a symbol. "

I think I understand that. It's currently a List, not a Symbol. So, I tried adding

SetAttributes[foo, HoldFirst];

after which I encountered another error:

TagSetDelayed::tagnf: "Tag a not found in {7,8,9}[i$_]."

Okay, so tag evaluated, I believe because it was in the form _[___]. So next, I added Unevaluated:

foo[tag_] := (
   tag /: Unevaluated[tag][i_] := tag[[i]]
   );

But this resulted in

TagSetDelayed::tagpos: "Tag a in Unevaluated[a][i$_] is too deep for an assigned rule to be found."

This, I don't understand...

share|improve this question
add comment

2 Answers

up vote 3 down vote accepted

Your problem has nothing to do with the function foo, but rather with the definition itself. Observe:

a = {7, 8, 9};

a /: a[i_] := a[[i]]

TagSetDelayed::tagnf: Tag a not found in {7,8,9}[i_]. >>

Because heads evaluate first you cannot even use the attempted definition for a while a has a direct (OwnValue) assignment:

ClearAll[a]
a /: a[i_] := z[i]

a = {7, 8, 9};

a[2]
{7, 8, 9}[2]

Further, TagSet serves no purpose here as you are actually defining a DownValue rule rather than an UpValue rule:

DownValues[a]
{HoldPattern[a[i_]] :> z[i]}
share|improve this answer
    
Thank you. I'm going to have to take some time to understand this. But meanwhile, could you confirm something? I'd like to be assign to the results of such an expression, i.e. a[2] = 42 to make a {7, 42, 9}. I'm essentially trying to write a function that implements @ssch's answer here: mathematica.stackexchange.com/questions/34850/…. I must retain the use of UpValues then, correct? (Perhaps I simplified the example too far.) –  Andrew Cheong Jan 25 at 18:13
    
@acheong87 That appears to be different from what you attempted in this question. I am not sure how ssch's method fails you. If you explain what you are actually trying to do I can probably help. Also, you may way to read this. –  Mr.Wizard Jan 25 at 18:47
    
Okay, I understand now that you're (of course) completely right; my issue had nothing to do with the passing of a symbol, but rather my attempt to define an UpValue on a symbol that already had an OwnValue (if that's the right way of describing it). My real question, it turns out, is, Is it possible for a symbol to (at least appear to) have both an OwnValue (data) as well as an UpValue (a setter/getter function)? Not sure if I should edit this question (making the current answers irrelevant), or if it's worth asking a new question. –  Andrew Cheong Jan 26 at 2:03
    
@acheong87 I think that would be better as a new question, but first make sure you understand what an UpValue is; as I noted your example in this question does not create an UpValue definition; an UpValue much be attached to a Symbol that appears as the head of an expression at level one in the left-hand-side pattern, such as a in {a[x_], y_} ^:= x^y –  Mr.Wizard Jan 26 at 2:36
add comment

Mr.Wizard told you what you did wrong but he didn't answer the implied question of how to accomplish what you want to do. Here is one way to do it.

ClearAll[foo, a];
SetAttributes[foo, HoldFirst];
foo[var_Symbol, data_List] := (Set[var[#], data[[#]]] & /@ Range[Length[data]])

foo[a, {7, 8, 9}];
a[2]
8

DownValues @ a

{HoldPattern[a[1]]:>7, HoldPattern[a[2]]:>8, HoldPattern[a[3]]:>9}
share|improve this answer
add comment

Your Answer

 
discard

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

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