Skip to main content
add performance comparison
Source Link
Oleksandr R.
  • 23.2k
  • 4
  • 88
  • 129

This is quite easy to achieve by direct manipulation of downvalues. Here's a simple example:

ClearAll[removeDownValues]; SetAttributes[removeDownValues, HoldAllComplete]; removeDownValues[p : f_[___]] := DownValues[f] = DeleteCases[ DownValues[f, Sort -> False], HoldPattern[Verbatim[HoldPattern][p] :> _] ]; 

Now let's memoize some values:

Do[f[1, i] = i, {i, 1, 10}]; DownValues[f] (* -> {HoldPattern[f[1, 1]] :> 1, HoldPattern[f[1, 2]] :> 2, HoldPattern[f[1, 3]] :> 3, HoldPattern[f[1, 4]] :> 4, HoldPattern[f[1, 5]] :> 5, HoldPattern[f[1, 6]] :> 6, HoldPattern[f[1, 7]] :> 7, HoldPattern[f[1, 8]] :> 8, HoldPattern[f[1, 9]] :> 9, HoldPattern[f[1, 10]] :> 10} *) 

If we no longer need some of these, we can remove them as follows:

removeDownValues[f[_, x_ /; 4 <= x <= 7]] (* -> {HoldPattern[f[1, 2]] :> 2, HoldPattern[f[1, 1]] :> 1, HoldPattern[f[1, 3]] :> 3, HoldPattern[f[1, 8]] :> 8, HoldPattern[f[1, 9]] :> 9, HoldPattern[f[1, 10]] :> 10} *) 

Performance will probably be fairly good if you need to remove a large number of memoized values at the same time, but you should bear in mind that resetting downvalues in this way requires rebuilding the hash table from scratch. As such, if you want to remove a few specific downvalues but do so many times, using Unset is probably a better choice. A timing comparison demonstrates that if you don't need to pattern match downvalues and can simply iterate over them instead, Unset is indeed preferable:

Do[f[1, i] = i, {i, 1, 1*^6}]; (* evaulated before each timing run below *) removeDownValues[f[1, x_ /; 1000 <= x <= 999000]]; (* 3.67 seconds *) removeDownValues[f[1, _]]; (* 3.39 seconds *) Do[f[1, x] =., {x, 1000, 999000}]; (* 2.03 seconds *) 

This is quite easy to achieve by direct manipulation of downvalues. Here's a simple example:

ClearAll[removeDownValues]; SetAttributes[removeDownValues, HoldAllComplete]; removeDownValues[p : f_[___]] := DownValues[f] = DeleteCases[ DownValues[f, Sort -> False], HoldPattern[Verbatim[HoldPattern][p] :> _] ]; 

Now let's memoize some values:

Do[f[1, i] = i, {i, 1, 10}]; DownValues[f] (* -> {HoldPattern[f[1, 1]] :> 1, HoldPattern[f[1, 2]] :> 2, HoldPattern[f[1, 3]] :> 3, HoldPattern[f[1, 4]] :> 4, HoldPattern[f[1, 5]] :> 5, HoldPattern[f[1, 6]] :> 6, HoldPattern[f[1, 7]] :> 7, HoldPattern[f[1, 8]] :> 8, HoldPattern[f[1, 9]] :> 9, HoldPattern[f[1, 10]] :> 10} *) 

If we no longer need some of these, we can remove them as follows:

removeDownValues[f[_, x_ /; 4 <= x <= 7]] (* -> {HoldPattern[f[1, 2]] :> 2, HoldPattern[f[1, 1]] :> 1, HoldPattern[f[1, 3]] :> 3, HoldPattern[f[1, 8]] :> 8, HoldPattern[f[1, 9]] :> 9, HoldPattern[f[1, 10]] :> 10} *) 

Performance will probably be fairly good if you need to remove a large number of memoized values at the same time, but you should bear in mind that resetting downvalues in this way requires rebuilding the hash table from scratch. As such, if you want to remove a few specific downvalues but do so many times, using Unset is probably a better choice.

This is quite easy to achieve by direct manipulation of downvalues. Here's a simple example:

ClearAll[removeDownValues]; SetAttributes[removeDownValues, HoldAllComplete]; removeDownValues[p : f_[___]] := DownValues[f] = DeleteCases[ DownValues[f, Sort -> False], HoldPattern[Verbatim[HoldPattern][p] :> _] ]; 

Now let's memoize some values:

Do[f[1, i] = i, {i, 1, 10}]; DownValues[f] (* -> {HoldPattern[f[1, 1]] :> 1, HoldPattern[f[1, 2]] :> 2, HoldPattern[f[1, 3]] :> 3, HoldPattern[f[1, 4]] :> 4, HoldPattern[f[1, 5]] :> 5, HoldPattern[f[1, 6]] :> 6, HoldPattern[f[1, 7]] :> 7, HoldPattern[f[1, 8]] :> 8, HoldPattern[f[1, 9]] :> 9, HoldPattern[f[1, 10]] :> 10} *) 

If we no longer need some of these, we can remove them as follows:

removeDownValues[f[_, x_ /; 4 <= x <= 7]] (* -> {HoldPattern[f[1, 2]] :> 2, HoldPattern[f[1, 1]] :> 1, HoldPattern[f[1, 3]] :> 3, HoldPattern[f[1, 8]] :> 8, HoldPattern[f[1, 9]] :> 9, HoldPattern[f[1, 10]] :> 10} *) 

Performance will probably be fairly good if you need to remove a large number of memoized values at the same time, but you should bear in mind that resetting downvalues in this way requires rebuilding the hash table from scratch. As such, if you want to remove a few specific downvalues but do so many times, using Unset is probably a better choice. A timing comparison demonstrates that if you don't need to pattern match downvalues and can simply iterate over them instead, Unset is indeed preferable:

Do[f[1, i] = i, {i, 1, 1*^6}]; (* evaulated before each timing run below *) removeDownValues[f[1, x_ /; 1000 <= x <= 999000]]; (* 3.67 seconds *) removeDownValues[f[1, _]]; (* 3.39 seconds *) Do[f[1, x] =., {x, 1000, 999000}]; (* 2.03 seconds *) 
Source Link
Oleksandr R.
  • 23.2k
  • 4
  • 88
  • 129

This is quite easy to achieve by direct manipulation of downvalues. Here's a simple example:

ClearAll[removeDownValues]; SetAttributes[removeDownValues, HoldAllComplete]; removeDownValues[p : f_[___]] := DownValues[f] = DeleteCases[ DownValues[f, Sort -> False], HoldPattern[Verbatim[HoldPattern][p] :> _] ]; 

Now let's memoize some values:

Do[f[1, i] = i, {i, 1, 10}]; DownValues[f] (* -> {HoldPattern[f[1, 1]] :> 1, HoldPattern[f[1, 2]] :> 2, HoldPattern[f[1, 3]] :> 3, HoldPattern[f[1, 4]] :> 4, HoldPattern[f[1, 5]] :> 5, HoldPattern[f[1, 6]] :> 6, HoldPattern[f[1, 7]] :> 7, HoldPattern[f[1, 8]] :> 8, HoldPattern[f[1, 9]] :> 9, HoldPattern[f[1, 10]] :> 10} *) 

If we no longer need some of these, we can remove them as follows:

removeDownValues[f[_, x_ /; 4 <= x <= 7]] (* -> {HoldPattern[f[1, 2]] :> 2, HoldPattern[f[1, 1]] :> 1, HoldPattern[f[1, 3]] :> 3, HoldPattern[f[1, 8]] :> 8, HoldPattern[f[1, 9]] :> 9, HoldPattern[f[1, 10]] :> 10} *) 

Performance will probably be fairly good if you need to remove a large number of memoized values at the same time, but you should bear in mind that resetting downvalues in this way requires rebuilding the hash table from scratch. As such, if you want to remove a few specific downvalues but do so many times, using Unset is probably a better choice.