# Is it possible to Clear (recover memory from) a specific index to a variable, while leaving other indices to the same variable untouched?

Consider the following method commonly used to clear a typical variable:

data = {1, 2, 3}
(* {1, 2, 3} *)

ByteCount[data]
(* 112 *)

Clear[data]

ByteCount[data]
(* 0 *)


No problem. Now, if I store the same information in an indexed variable, problems arise.

mytest[data] = {1, 2, 3}
(* {1, 2, 3} *)

ByteCount[mytest[data]]
(* 112 *)

Clear[mytest[data]]

During evaluation of Clear::ssym: mytest[data] is not a symbol or a string.

ByteCount[mytest[data]]
(* 112 *)


Is there a way to clear the values of indexed values so they don't consume memory?

My primary application requires large volumes of data to be stored in indexed variables, and at appropriate times, I would like to be able to "erase" that data from memory as my datasets are really big (multiple GBs per file).

Following initial comments, I realized I needed to re-word my initial question. (which I've done.) Taking advice from the comments, it seems Unset may be the way to go here.

Notice:

mytest[data] = {1, 2, 3}
(* {1, 2, 3} *)

mytest[data2] = {4, 5, 6, 7}
(* {4, 5, 6, 7} *)

ByteCount[mytest[data]]
(* 112 *)

ByteCount[mytest[data2]]
(* 136 *)

mytest[data] =.

ByteCount[mytest[data]]
(* 48 *)

mytest[data]
(* mytest[data] *)

mytest[data2]
(* {4, 5, 6, 7} *)


As an add on, why is there a small amount of memory still attached to mytest[data] after performing the Unset operation?

• ClearAll[mytest]? – kglr Aug 5 '19 at 16:40
• Alternatively, you could use Unset: mytest[data] =. – Michael E2 Aug 5 '19 at 16:41
• Beware that the values might have also been bound to Out so you might need to clear that too if you really need the memory back. – b3m2a1 Aug 5 '19 at 16:59
• @kglr After reading your response, I realized my initial question was not defined as specifically as it should have. I need to clear memory from a specific index while leaving data associated with other indices untouched. I've modified my question and thank you for responding. – Todd Allen Aug 5 '19 at 18:20
• @ToddAllen, so wait, what is wronog with Unset? – ktm Aug 5 '19 at 18:26

Byte count is 64, for entry in indexed variable. Even if there is no data

As mentioned in comment, use =. to clear specific index

Too long for a comment:

ByteCount[mytest[data]] measures the memory required for the expression mytest[data]. The ByteCount of a Symbol is always zero; see the docs for ByteCount:

Symbols are effectively always shared, so they give 0 byte count:

In other words (I think), it does not count the memory required to store the symbol in the symbol/hash table.

The OP's first ByteCount[data] computes ByteCount[{1, 2, 3}] because data evaluates to the expression {1, 2, 3} before ByteCount is called. Consider

Trace[ByteCount@data]
(*  {{data, {1, 2, 3}},
ByteCount[{1,2,3}],
112}  *)


Also consider the difference between the evaluated and unevaluated data:

data = {1, 2, 3};
ByteCount /@ {data, Unevaluated@data}
(*  {112, 0}  *)


@Nasser's example ByteCount[a[1]] gives 64 bytes and the OP's ByteCount[mytest[data]] gives 48 bytes (after data is cleared). Here is an accounting of it:

Clear[a, b];
ByteCount@ 1
ByteCount@ a[b]
ByteCount@ a[1]
(*
16  - storage of one integer
48  - storage of the head--argument tree expression
64  - total
*)


One can carry this accounting game further. For instance, ByteCount@ 2[1] gives 80. However, beware that according to the docs,

ByteCount will...often give an overestimate of the amount of memory...needed....

Back to the principal question, which has already been answered, how to free up memory when a value is no longer needed:

See the docs for more information. As has been noted in the comments and @Nasser's answer, Unset is the desired solution in the OP's case.

• Thank you for the follow-up. It is detailed responses like this that really start to peel back the "petals of ignorance." Much obliged. – Todd Allen Aug 6 '19 at 0:18