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.

I've got a situation where I have, say 4 symbols, a, b, c and d. This is a simplification of the issue I've been working with. Let's say I assign numeric values to these symbols:a=1; b=2; c=3; d=4. I now create a list: myList:={a,b,c,d}. I'd like to be able to say: ( # = 5 ) & /@ myList to assign the value 5 to a, b, c and d. The code works as long as a-d are unassigned. Is there a way to do this, or am I trying to abuse the language?

share|improve this question
    
What exactly is your aim in general? (To understand your example, look at the output of Trace[myList:={a,b,c,d}] and of Trace[myList={a,b,c,d}]. The former is a mistake while the latter attempts to issue a sequence of Set assignments 1=5, 2=5, ..., 4=5.) –  whuber Jan 19 '12 at 15:01
4  
FYI: It's a bit better to use Scan[] instead of Map[] (that is, /@) for multiple assignments. –  J. M. Jan 19 '12 at 15:01
    
A primary aim of mine is to be able to make a bunch of reassignments using map, rather than writing all of the assignment statements. Another aim is to use meaningful names for the symbols and then being able to retrieve the name of the symbol, along with any values I assign to it. Typically the symbols will represent lists, I just used integers to make it easier to write out an example. –  Mitchell Kaplan Jan 22 '12 at 22:34
add comment

5 Answers 5

This seems to work:

a = 1; b = 2; c = 3; d = 4;
Scan[Function[p, p = 5, HoldAll], Hold[a, b, c, d]]

Now, try evaluating {a, b, c, d}.

Here's the version with slots:

    Scan[Function[Null, # = 5, HoldAll], Hold[a, b, c, d]]
share|improve this answer
3  
+1, Though it's very logical, I didn't realize Scan can be used in such a way on held expressions. This is an important difference between Scan and Map, that your answer highlights. –  Szabolcs Jan 19 '12 at 15:23
    
@Szabolcs I second that. Did not realize it either. –  Leonid Shifrin Jan 19 '12 at 15:59
    
@J.M +1 out of curiosity how did you figure out this behaviour. I've just had a scan (pun intended) of the documentation and I don't think you would know that this would work for this example from the description there. –  Mike Honeychurch Jan 19 '12 at 23:07
3  
@MikeHoneychurch Now that I see that it works, it seems very logical: Map modifies the expression, Scan takes parts of the expression and runs f[part] for each. Is our way of thinking too constrained maybe? This is why I love this site and interaction with others :-) You always learn something new –  Szabolcs Jan 20 '12 at 11:56
1  
+1, a slightly shorter variant: Scan[Function[p, p = 5, HoldAll], Hold[a, b, c, d]] –  WReach Jan 21 '12 at 19:26
show 4 more comments

You could use

myList = Hold[a,b,c,d]

Function[x, x=5, {HoldAll}] /@ myList // ReleaseHold
share|improve this answer
add comment

If you insist on working with your list where you assemble variables, this will do it:

setValues  =
   Function[{vlist, val},
      OwnValues[vlist] /. (_ :> vars_) :>
        Replace[Unevaluated@vars, var_ :> (var = val), {1}],
      HoldFirst];

For example:

In[73]:= myList:={a,b,c,d}
In[74]:= a=1;b=2;c=3;d=4;

In[77]:= setValues[myList,5];

In[78]:= myList
Out[78]= {5,5,5,5}
share|improve this answer
    
Very cool, I was writing up something very similar. +1 –  acl Jan 19 '12 at 15:19
1  
@acl Thanks. Didn't intend to steal your answer. But it seems like there will be enough cool questions for all of us. –  Leonid Shifrin Jan 19 '12 at 15:21
    
Oh no, I didn't mean that! Your code is shorter and neater than mine anyway. –  acl Jan 19 '12 at 15:30
add comment

We can define a new "variable container" that can be used to assign the same value to multiple variables:

ClearAll[vars]
SetAttributes[vars, HoldAll]
vars /: s:(_vars = _) := CompoundExpression @@ Thread[Unevaluated@s, vars, 1]

It is used like this:

In[4]:= ClearAll[a, b, c, d]
        vars[a, b, c, d] = 5
Out[5]= 5

In[6]:= {a, b, c, d}
Out[6]= {5, 5, 5, 5}

In[7]:=  vars[a, b, c, d] = 66
Out[7]=  66

In[8]:=  {a, b, c, d}
Out[8]=  {66, 66, 66, 66}

In[9]:=  vec = {1, 2, 3, 4};
         vars[vec[[2]], vec[[4]]] = 999
Out[10]= 999

In[11]:= vec
Out[11]= {1, 999, 3, 999}
share|improve this answer
    
Late answers rarely get the attention they deserve. (This one wasn't even very late.) Long overdue +1. –  Mr.Wizard Aug 18 '13 at 2:49
add comment

One could use Outer for this purpose:

{a, b, c, d} = {1, 2, 3, 4};

Outer[Set, Hold[a, b, c, d], Hold[5], 1] /. Hold -> List

or:

{a, b, c, d} = {1, 2, 3, 4};

Outer[Set, Unevaluated[{a, b, c, d}], {5}, 1]

Thread also works:

{a, b, c, d} = {1, 2, 3, 4};

Thread[Hold[{a, b, c, d}, 5]] /. Hold -> Set
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.