5
$\begingroup$

I want to be able to assign values to a list element inside a module. For example if I have:

testscan[listin_] := 
 Module[{zz}, 
  Do[listin[[1]] = zz; Print[{zz, listin[[1]]}], {zz, 1, 2, 1}]]

Given:

testscan[{a, 1, 3, 1}]

Returns:

{1,a}

{2,a}

What I want it to return:

{1,1}

{2,2}

So its not just the output I care about, I want 'a' in this case to be able to reassigned to anything. Any ideas? Thanks a lot for your time.

LH- it is indeed a that I want to modify. The page you linked to is on the right track, but doesn't quite give me what I need yet. For example using your setPart function:

in:

foo = {a, 1, 3, 1};
setPart[foo, 1, xxx];
foo                          

out:

{xxx, 1, 3, 1}                                              

But then for:

IN:

Clear[listin];
testscan[listin_] := 
 Module[{}, setPart[listin, 1, \[Pi]]; Print[{listin[[1]], listin}]]                                                             
testscan[{a, 1}]                                                      

out:

{a,{a,1}}

So setPart doesn't seem to work inside modules as the way I have it. Can you offer my any further assistance? Again, thank you so much for your time.

Leonid - I am fairly new to Mathematica so I wasn't sure about these subtleties, but now its pretty clear that indeed I am just trying to find workarounds instead of a proper solution. The 'true' problem I am working on is trying to scan a parameter space of varying numbers of parameters subject to some constraints (I am interested in any number of constraints just out of curiosity, but in reality no more than 2 constraints in the actual). So it would look something like :

TestScan[c1,...,cm,{list1,....listn}]

Where the ci are constraints and the list_i's take the form {x_i,x_i_initial, x_i_final, x_i_increment} that will be fed to a Do loop.

For example I might have a constraint like x^2+y^2+z^2=1, I want to scan over values of y and z, solve for the corresponding values of x, then store all the possible solutions in a list. By putting the variables I want to scan over in an array it seems easier since then I can have Mathematica see the size of the array, and run the proper number of Do loops. Obviously if I just put the variables in a function like

TestScan[c1,...,cm,x_i,x_i_initial, x_i_final, x_i_increment,....]

it works, but I would have to change the code every time I change the number of variables in the constraints. So this to me boils down to my earlier question of how to make Mathematica see a part of a list as a variable that I can then increment in a Do loop inside a Module.Do you have any advice how I could achieve this without such work-arounds, and hopefully without bothering you any more? Thanks a ton for your time. DB

$\endgroup$
1
  • $\begingroup$ Addressing your edit: this has nothing to do with Module. If you want to modify list elements persistently, you have to store the list in a variable, as I mentioned (instead, you again pass the list directly, and ignore my advice on Hold-attribute for testscan). Generally, what you try to achieve is going against the semantics of Mathematica regarding assignments/part modifications. Therefore, the work-arounds will likely be complex and lead to more questions. I would rather give a larger context of your real problem - it is more than likely that better alternative solutions exist. $\endgroup$ Commented Mar 21, 2012 at 10:41

1 Answer 1

11
$\begingroup$

You should have included the error messages. There are several problems with this code. First, you can only assign to parts of an expression, if it is stored in some symbol. This is because expressions are immutable in Mathematica. I discuss this here. In your case, you pass the list itself. So, the first step would be to use pass-by-reference semantics (emulated by Hold - attributes) and write

SetAttributes[testscan, HoldAll];
testscan[listin_] := 
  Module[{zz}, 
     Do[
       listin[[1]] = zz; Print[{zz, listin[[1]]}], 
       {zz, 1, 2, 1}
     ]
  ]

and then use it as

lst = {a, 1, 3, 1};
testscan[lst]

which gives the desired outcome, bacause now the input list is stored in a variable which is passed unevaluated (as a reference, more or less).

It is important to note however, that the a in lst was not modified, but rather replaced by new values, so that now

?lst

Global`lst
lst={2,1,3,1}

If you really want to modify a, I recommend reading this answer.

$\endgroup$
3
  • $\begingroup$ Hi Leonid- First of all, thank you very much for your time. I indeed want to modify a itself. The page you linked to is definitely on the right track, but doesn't quite give me what I need yet. I had to add my full comment above since it won't fit here. $\endgroup$
    – DJBunk
    Commented Mar 21, 2012 at 1:53
  • $\begingroup$ Again, I had to put my reply above. Thanks. DJB $\endgroup$
    – DJBunk
    Commented Mar 21, 2012 at 14:06
  • $\begingroup$ @user793 I would suggest to take that new problem and ask it as a separate question, since it is sufficiently different from the original question you asked. This is a normal practice here, when one question leads to another one etc. Then, I or other folks will try to help. One thing I suggest though is to provide some minimal self-contained example (in code) - if at all possible, that doesn't work - just as you did for your original question. $\endgroup$ Commented Mar 21, 2012 at 14:29

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.