4
$\begingroup$

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]]}
$\endgroup$
2
  • $\begingroup$ 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. $\endgroup$ May 2, 2013 at 8:59
  • $\begingroup$ 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). $\endgroup$
    – bill s
    May 2, 2013 at 9:31

2 Answers 2

3
$\begingroup$

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}
$\endgroup$
4
  • $\begingroup$ This is very cool. +1 $\endgroup$ May 3, 2013 at 8:13
  • $\begingroup$ @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? $\endgroup$
    – Mr.Wizard
    May 3, 2013 at 13:51
  • $\begingroup$ 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... $\endgroup$ May 3, 2013 at 15:19
  • $\begingroup$ @Simon How I feel about my own memory: youtube.com/watch?v=ClgLvztrXbk $\endgroup$
    – Mr.Wizard
    May 3, 2013 at 15:36
3
$\begingroup$

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.

$\endgroup$
4
  • $\begingroup$ 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} $\endgroup$
    – matheorem
    May 2, 2013 at 14:25
  • $\begingroup$ 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 =. $\endgroup$
    – andre314
    May 2, 2013 at 18:16
  • 1
    $\begingroup$ a little comment : Stack Exchange is not a chat. One Question at a time. $\endgroup$
    – andre314
    May 2, 2013 at 18:37
  • $\begingroup$ 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. $\endgroup$
    – matheorem
    May 3, 2013 at 0:10

Your Answer

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

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