Simple question, but I am asking just to make sure I am not overlooking an obvious solution which can be much more efficient.
If one has large data buffer, say very large list, that needs to be updated, and wanted to pass it to a function to do the updating inside the function as in
a = Table[0,{10}]
a = update[a]
and since I can't use pass by reference (in a CDF, one can't change the Atrributes of a function to anything, such as HoldFirst), then I am forced to make a copy of the list inside the function itself in order to update it, and return back the copy.
My question, other than using 'global variables' which is not good, is there a more efficient way to do this?
ps. about a year ago, I asked about copy by reference, here is a link to my Mathgroup question. (Thanks to Leonid answer there btw, was useful answer).
But my question here is a little different, since now I can NOT use HoldFirst, are there any other alternatives that I am not seeing to avoid this extra copying of data all the time, it seems to slow down the program when the size becomes too large.
(can't use SetAttributes and its friends, not allowed in CDF).
I'll show the basic example first, then show how I would do it if I could use the HoldFirst.
Example
update[a_List] := Module[{copyOfa = a}, copyOfa[[1]] = 5; copyOfa]
a = Table[0, {10}];
a = update[a]
----> {5, 0, 0, 0, 0, 0, 0, 0, 0, 0}
If I could use the HoldFirst, I would write
update[a_] := Module[{}, a[[1]] = 5; a]
Attributes[update] = {HoldFirst};
a = Table[0, {10}];
a = update[a]
----> {5, 0, 0, 0, 0, 0, 0, 0, 0, 0}
Much more efficient, since no copying is done. Pass by reference.
I could use a global variable, as in
a = Table[0, {10}];
updateMya[] := Module[{}, a[[1]] = 5]
updateMya[];
a
----> {5, 0, 0, 0, 0, 0, 0, 0, 0, 0}
But this is of course bad programming even if is it very fast.
Since I have large data buffers, and I'd like to modularize my Mathematica code, I need to create functions that I pass it large data to process, but at the same time wanted to keep it 'efficient'.
Any other options one can see to do this?
sorry if this was asked before here, hard to search SO.
thanks,
addition 1
Using Unevaluated is easy to use, but I am no longer able to use the type checking I had to make sure that a list is being passed. For example
update[a_List] := Module[{}, a[[1]] = 5; a]
a = Table[0, {10}];
a = update[Unevaluated[a]]
The call now does not 'bind' to the definition, since 'a' now does not have header List.
So, I lose some of the robustness I had in the code. But using Unevaluated does work in CDF and changing the code to use it was easy. I just had to remove those extra 'type checking' that I had there to make it work.
update[a_]/;Head[a]===List:=...
. – BukharaEvaluate
insideHead
(since a new sub-evaluation is induced for that). I should find some time to correct it. – Bukhara_List
(and similar), and because it does evaluate the argument inHead
. This does not matter in this case, but may matter if the supplied argument is a code with side effects. For example, fori=0;update[i++]
, I arguably should not incrementi
in the process of type-checking (so the value ofi
after we execute this code should still be0
). A safer solution can be worked out, but will be more complicated and will also induce even larger overhead. – Bukhara