1

I have already asked a related question here why set values in this way doesn't work? But I think I have to write the question which I encountered explicitly?

tmp = {1, 2, 3, 4, 5}
label[i_, p_] := i + p
test[p_] := Table[tmp[[label[i, p]]], {i, 1, 2}]

Here I defined a function test and the thing I want to is that change the values of list tmp via setting values to function test. While simply write

test[1]={111,222}

and expecting tmp will change to {1,111,222,3,4,5} is not possible.

So how to achive this? I have tried many Hold things, but failed.

Inspired by andre. I know that Set has attribute HoldFirst. So I tried Evaluate

 Evaluate[test[1]]={111,222}

this won't work! I guess the problem is that I must properly Hold label[i,p] and tmp[[]] in the table. But I can't work it out. Anyone help?

matheorem
  • 17,132
  • 8
  • 45
  • 115

1 Answers1

3

This seems rather convoluted, and there is almost certainly an easier way to approach whatever it is you are wishing to do, but I like answering questions like this as it allows working with more unusual aspects of the language.

We can do this:

Block[{tmp, Part}, Hold @@ {test[2]}] /. _[x_] :> (x = {111, 222});

As with my previous answer we may wish to wrap this into a more convenient syntax, but there is a problem; how do we know that tmp is the symbol to be blocked? We can give it explicitly, if that is acceptable.

func_[boost2[expr_, sym__], arg___] ^:= 
  Block[{sym, Part}, Hold @@ {expr}] /. _[x_] :> func[x, arg]

Use syntax:

boost2[test[1], tmp] = {111, 222};

I'm not certain if there is any point in keeping the generalized form of this function in analogy to the original bump function, but it was easy for me to write it this way. If you wish only to have this operation apply to Set it may be simpler to write a mySet analog, like this:

SetAttributes[mySet, {HoldAll, SequenceHold}]

mySet[expr_, sym__, value_] := 
  Block[{sym}, Hold @@ {expr} // Quiet] /. _[x_] :> (x = value)

mySet[test[1], tmp, {111, 222}]

To me this syntax is not as elegant as the form above.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Thank you Mr.Wizard. Sorry for the late comment. I spent 10 hours reading mathematica docs and doing experiment on mathematica.In the end, I still can't make all that clear. I am really frustrated with my IQ. So here is the question, I think I don't have a good understanding ofBlock. For example, Why x=7;Block[{x},Print[x]] gives x not 7?? why Block[{tmp},Hold@@{tmp[[1]]}]gives Hold[tmp[[1]]], while Hold@@[tmp[[1]]] gives 1 ?? And why your code include Part in the Block list. I tried remove the Part, though it will give error message, but the tmpreally changes. – matheorem May 03 '13 at 13:49
  • And I really don't understand func_[boost2[expr_, sym__], arg___] ^:= . Why there is a Blank after func? what does it mean? – matheorem May 03 '13 at 14:09
  • @matheorem You should read this; I particularly like WReach's answer as it succinctly summarizes the behavior of these functions. The reason I Block tmp and Part is to prevent either of them from evaluating inside the Block[ . . . ] allowing me to easily manipulate the expression without it evaluating all the way. – Mr.Wizard May 03 '13 at 14:44
  • @matheorem the definition func_[boost2[expr_, sym__], arg___] ^:= is more complicated than it may need to be for your application. It is an UpSetDelayed definition that will attach an UpValue to boost2. The pattern func_ will match any head (function) with arguments of the form boost2[expr_, sym__], arg___. Please review this documentation page. – Mr.Wizard May 03 '13 at 14:48
  • @matheorem I just noticed an error in my code above which I will correct now. I will also add another example. – Mr.Wizard May 03 '13 at 14:51
  • I corrected the error; in the new method I also removed Part from Block and added Quiet instead to suppress the error messages. Either method may be used at your preference. – Mr.Wizard May 03 '13 at 14:58
  • Thank you very much! I had been trying to think of other ways to do this, but all failed. And I have fully understood your thoughts of dealing this problem. Block together with Hold and then apply ruledelayed to achive the assignment, this approach is powerful and general!! You're awesome!! – matheorem May 04 '13 at 14:41
  • Sorry for bothering you again, Mr.Wizard. I have some more questions. First, I found that in the definition of function boost2. the sym in the Block will be red. It seems that Mathematica think it is not right to write in this way. But why there is no any error message when using boost2. Second, I tried to define a seperate function that severs holding a table expression. I call it holdtable. holdtable[tableexpr_, tobeheld__] := Block[{tobeheld, Part}, Hold @@ {tableexpr}]But when I use holdtable like holdtable[test[1],tmp], the result is not right. tmp is not blocked. – matheorem May 05 '13 at 02:17
  • @matheorem there are a number of places where "warning" syntax highlighting is applied to perfectly valid code; this is one of them. Think of it as a "this may not work as you expect" warning. Also, on your holdtable did you remember to set the HoldAll attribute as I did for my mySet function? – Mr.Wizard May 05 '13 at 16:19
  • Thank you Mr.Wizard! I maybe a little anoying. But I have to make things clear, otherwise I will be very uncomfortable. Now I see I have to set HoldAll attribute to tobeheld, because otherwise it will be evaluated before being passed to Block. And I think that's why MMA make tobeheld red, the red is quite reasonable to prevent error. – matheorem May 06 '13 at 02:13
  • But why boost2 doesn't have to be set to HoldAll?Of course, the code is more complicated than holdtable. It is a upsetdelayed and there is pattern match. But I didn't find the key to explain why the red in the definition of boost2 is valid. I found that if I don't let func to be Set when using boost2, for example, I write Join[boost2[test[1],tmp],{111,222}] then the tmp passed to Block has been evaluated. This confused me a lot. I seems boost2 is not perfect, right? – matheorem May 06 '13 at 02:13
  • @matheorem You're not annoying, but this is probably better explained in Chat. Unfortunately I don't have time tonight but I'll leave one more comment. (1) The red highlighting is not because of any hold attribute or a lack thereof, but rather because the same symbol is used in a pattern in the left side of the ^:= definition, which is a form of scoping construct, and also in the Block which is another scoping construct. Compare with Block[{x}, Block[{x}, 5]]. (2) HoldAll was not needed for boost2 because it is an UpValue and Set has HoldFirst; the rule acts before evaluation. – Mr.Wizard May 06 '13 at 03:05