0
$\begingroup$
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...

$\endgroup$

2 Answers 2

3
$\begingroup$

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]}
$\endgroup$
4
  • $\begingroup$ 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.) $\endgroup$ Commented Jan 25, 2014 at 18:13
  • $\begingroup$ @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. $\endgroup$
    – Mr.Wizard
    Commented Jan 25, 2014 at 18:47
  • $\begingroup$ 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. $\endgroup$ Commented Jan 26, 2014 at 2:03
  • $\begingroup$ @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 $\endgroup$
    – Mr.Wizard
    Commented Jan 26, 2014 at 2:36
1
$\begingroup$

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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