4

question is as follows

define a list

ttt={1,2};

and if I set values in this way

{ttt[[1]],ttt[[2]]}={3,4}

then the value of list ttt now becomes {3,4}

Now I try this

f:={ttt[[1]],ttt[[2]]}

then ?f will show that f:={tmp[[1]],tmp[[2]]}

then if I just write

f={3,4}

this will not affect the values of list ttt .

the question is that I want the values of list ttt changes as well when I set values to f. How to do this?


More Question!!

why the following code didn't change the value of ttt??

Table[With[{i = i}, Defer@ttt[[i]]], {i, 1, 2}] = {111, 222}

while

Table[With[{i = i}, Defer@ttt[[i]]], {i, 1, 2}]

really gives

{ttt[[1]],ttt[[2]]}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
matheorem
  • 17,132
  • 8
  • 45
  • 115
  • The assignment to list part (ttt[[3]]=val) only works, if the list part is at the left hand side of the Set operator (as Set has attribute HoldFirst), otherwise it simply returns the appropriate element of ttt. – István Zachar May 02 '13 at 08:59
  • You can make ttt change when f changes by using SetDelayed, as in ttt:=f. But it sounds like you are trying to do this at the same time as you set f:=ttt. You can't do both at once because it creates a circle (you will get a recursion error). – bill s May 02 '13 at 09:31

2 Answers2

3

You may use ReleaseHold[Hold[f = {3, 4}] /. OwnValues[f]] :

ttt = {1, 2};
f := {ttt[[1]], ttt[[2]]};

ReleaseHold[Hold[f = {3, 4}] /. OwnValues[f]]

?ttt

(* ttt -> {3,4} *)

Some explanations :

  • The fullform of f={3,4} is Set[f, List[3, 4]].
  • Set has attribute Holdfirst.
  • We want to transform Set[f, List[3, 4]] in {ttt[[1]], ttt[[2]]}={3,4}.

So :
-f must be evaluated, that is to say f must become {ttt[[1]], ttt[[2]]}
- but {ttt[[1]], ttt[[2]]} must not be further evaluated to {1,2}.

The idea is to manually control the evaluation process with Holdand ReleaseHold. I use too the fact that /. x->y is effective inside a Hold.

Otherwise, OwnValues[f] gives the internal rule attached to f (with Down Values,UpValues...). The rule attached to ttt are not used.

To see what's happening, one can use ReleaseHold[Hold[f = {3, 4}] /. OwnValues[f]] // Trace // Column. It is not too much verbose.

NB : The fact that Set has attribute HoldFirst seems a little bit contradictory with the fact that {ttt[[1]],ttt[[2]]}={3,4} works. I have used a partially "try and see what's happening" approach to find the solution.

andre314
  • 18,474
  • 1
  • 36
  • 69
  • Thank you very much! Can I ask another question? Why this code doesn't work? Table[With[{i = i}, HoldForm@ttt[[i]]], {i, 1, 2}] = {111, 222} – matheorem May 02 '13 at 14:25
  • There are several reasons. The main one is that when you write Table[...]]=... , Table[... is not evaluated (because it's the fist argument of Set), that is to says it simply stays inert. Set[...] treats most expressions like this. Lists (as in {x,y}=...) are exceptions (x and y are "extracted" from the expression {x,y}). I think a general rule of thumb is to autorise only lists and symbols to be on the left side of a =. – andre314 May 02 '13 at 18:16
  • 1
    a little comment : Stack Exchange is not a chat. One Question at a time. – andre314 May 02 '13 at 18:37
  • Thank you andre! So there is no way to set values to Table directly? I really need to do it this way, because I have defined a function which is a table, with different argument, the table will be different. And I want to set values to the table list in the program. – matheorem May 03 '13 at 00:10
3

I would approach this by combining the functionality of bump given in:
Elegant manipulation of the variables list
with my step evaluation function described here:
How do I evaluate only one step of an expression?

The step function is needed to (easily) recover the expression {ttt[[1]], ttt[[2]]} from the definition of f without it fully evaluating. It can be used like this, with the injector pattern:

ttt = {1, 2};
f := {ttt[[1]], ttt[[2]]}

step[f] /. _[x_] :> (x = {3, 4})

ttt
{3, 4}

To make this more convenient, and to work with other functions (see the first question linked above for examples) I would then write (after loading step):

func_[boost[expr_], arg___] ^:= step[expr] /. _[x_] :> func[x, arg]

Example of use:

boost[f] = {5, 6};

ttt
{5, 6}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • This is very cool. +1 – Simon Woods May 03 '13 at 08:13
  • @Simon Thank you. :-) I have yet to find as nice a way to approach something like this as to use step; I find a lot of use for that function since writing it. Out of curiosity, are you using it for anything? – Mr.Wizard May 03 '13 at 13:51
  • No, but I will in future! I must have seen it before, as I'd already upvoted the question and answer, but I'd forgotten about it. Stupid memory... – Simon Woods May 03 '13 at 15:19
  • @Simon How I feel about my own memory: http://www.youtube.com/watch?v=ClgLvztrXbk – Mr.Wizard May 03 '13 at 15:36