Suppose I have the following:
Table[x[i,j] = f[i,j], {i,1,10},{j,1,10}];
I want to set variables x[i,j]
to have value f[i,j]
where f
can be anything. The Table
(and you could also achieve this with a Map
and I'm sure many other ways) produces an undesirable list which will be discarded. This is a waste of memory, especially if f
produces some large object, and the copies will have to be garbage collected even though I've suppressed the output.
To avoid this behaviour for lists I would normally do a Scan
like this example in the documentation:
test = Scan[(u[#] = x) &, {55, 11, 77, 88}]
It sets u[55], u[11], u[77], u[88]
without creating any intermediate lists and test
is Null
.
Compare this with a Map
where test
is populated with the values on the RHS of the Set
. Also note this test
return value is for illustrating the idea only and I expect to discard it:
test = Map[Set[u[#],x] &, {55, 11, 77, 88}];
Question:
How can I use
Scan
over a multidimensional list such asTuples[Range[10],2]
to achieve the same effect as theTable
example at the top of this question? I am not interested in using aFor
loop and I am only interested in achieving this withScan
if that's possible.Are my fears about the discarded return values wasting memory and adding to garbage collection time justified if the object on the RHS of the
Set
is very large? Can Mathematica tell when aTable
orMap
is about to discard the list they build up and avoid creating one? I suspect not e.g tryMaxMemoryUsed[Table[x, 300000];]
Update:
Scan
appears to be consistently worse for memory usage, much to my surprise. Why? Surely it can't be because of the Range
that must be constructed first, because MaxMemoryUsed[Range[10000]]
is only 80376 bytes.
f[i_] := RandomReal[i, {64, 64}];
MaxMemoryUsed[Scan[(x[#] = f[#]) &, Range[10000]]]
ClearSystemCache[];
MaxMemoryUsed[Table[y[i] = f[i], {i, 10000}]]
ClearSystemCache[];
MaxMemoryUsed[Do[z[i] = f[i], {i, 10000}]]
ClearSystemCache[];
Scan
to begin with and the answer doesn't even use aScan
so it's not that relevant. $\endgroup$Do
can be thought of a as a drop-in replacement forTable
when the list is not necessary. $\endgroup$For
,Do
,While
etc. $\endgroup$(u[##] = f[##]) & @@@ {{4, 4}, {5, 2}, {4, 3}}
(The latter are just some random sample locants) $\endgroup$test = (u[##] = f[##]) & @@@ {{4, 4}, {5, 2}, {4, 3}};
is not Null. It creates a list of results which needs to be garbage collected - which is fine if the items produced byf
are small, but slow if they are large. This is not an XY problem, I'm only interested in how to do it withScan
- I already know several other ways to achieve the same effect as theMap
orTable
approach. $\endgroup$