I have the following problem: I would like to control evaluation of a variable that points to a list. For example, frequently in the code I have functions of the form that are supposed to work on large lists (modifying them frequently):
updateList[list_, newvalue_, index_]:= (list[[index]] = newvalue) to be used (many times) as
list = {1, 2, 3}; While[... updateList[list, -2, 2]; ] and I should get immediately
list = {1, -2, 3} The problem is that the list gets evaluated immediately if one is not careful and the assignment statement fails. I have tried to solve this by defining
Attributes[updateList] = {HoldAll} It works, but I realized that this can get very complicated since I am passing the list quite a bit around in a rather big package. Some function have Hold, some not, on some I would actually like to have the second and the third argument Holding while others not... To tell you the truth, I do not feel I have the control of this behavior; sometimes it evaluates and sometimes it does not, and it is driving me crazy.
The reason why I am doing this is to save memory. One could, of course, use the following definition
updateList[list_, newValue_, index_] := (newList = list; newList[[index]] = newvalue) and use it like
list = updateList[list, -2, 2] to the same effect, but this will consume quite a bit of memory (my list are huge). So I am trying to control memory usage by updating storage. I guess I am trying to use them as pointers.
A more serious example would be
updateList[list_, args__] := Block[{indicies, newvalues}, indicies = figureOutIndiciesToChange[args]; newvalues = figureOutValuesToChange[args]; list[[indicies]] = newvalues ]; or even a more nasty example (actually happens):
updateList[list_, args__] := Block[{indicies, newvalues}, indicies = figureOutIndiciesToChange[args]; nestedCallToUpdateTheList[...., list, ...]; newvalues = figureOutValuesToChange[args]; list[[indicies]] = newvalues ]; where
(* here list can be third argument, or even last *) nestedCallToUpdateTheList[...., list_, ...] := While[a big loop, list[[dynamicIndicies] = dynamicValues]]; ] So I have a principle (open) question: how to update long lists (parts of it) in the most efficient way if such lists are passed through several layers of functional calls? Is there a way to achieve this without using HoldAll? Perhaps using more direct Hold functionality? Anyway, I would like to learn how to be in control...
EDIT1: Based on the comments below, I would like to add another requirement; Assume that all this has to be done within the function. Is this possible at all? A bullet-proof way would be
updateLilst[___] := fail["please used Hold on the list argument"]; updateList[...,list_Hold,...] := do the work on the list; Or...?
EDIT2: By the way, how to test whether an argument is evaluated in the function?
p.s. I tried with Hold, but it is tricky since it is not make the assignment with a Held variable...
list[[2]]=-2directly to modify the list? tutorial/AddingRemovingAndModifyingListElements $\endgroup$Set[Part[list, 2], -2]if you prefer that notation. And neither clones the list, after:list = {1, 2, 3, 4, 5}; list[[2 ;; 3]] = -1;list will be modified solist=={1,-1,-1,4,5}$\endgroup$