ClearAll::clloc - "Cannot clear local variable x" in Block[{x}, ...] - why?

Block[{x}, ClearAll@x]


ClearAll::clloc: Cannot clear local variable x.

The documentation just says

An error occurs because ClearAll cannot be used with a local variable in Block:

and

This message is generated when ClearAll is used with a local variable in Block or with a similar local variable in another function.

Why is ClearAll forbidden in Block?

I can do the clearing manually myself afterall, it just takes quite a few calls to Unset:

Block[{x}, x = 0; Echo@x; x =.; Echo@x]


0

x

On that note, has anyone written a custom implementation of ClearAll I could use for this?

As for the documentation, what do they mean with the part "or with a similar local variable in another function"? What other conditions raise this message?

• +1 but ClearAll =!= Unset. E.g. Clear is closer and does not rise a message.
– Kuba
Aug 31 '16 at 21:43
• The comment in the documentation might refer to things like Table[ClearAll[x], {x, 10}]. Just a guess. Sep 1 '16 at 7:46
• Interestingly ClearAttributes can be used in a Table. Sep 1 '16 at 20:26
• Using Remove instead of ClearAll works. But it also impacts the global x and therefore should probably create a message too. Sep 3 '16 at 13:00
• The reason why I set a bounty on this is that I would like to get more insight about why ClearAll should be forbidden for Block variables. What is it that ClearAll clears that would cause trouble inside of Block? Here's a list of what I believe ClearAll does: mathematica.stackexchange.com/a/125195/12 None of these seem to be forbidden when tested individually. Sep 5 '16 at 8:24

This is an implementation detail in some sense, but I will try to give an explanation of sorts (perhaps too simplistic).

For any given symbol, there can be multiple sets of values (say OwnValues, DownValues etc.) associated with it.

Inside a Block there is a currently active set of values, but the kernel also keeps track of one or more previous sets of values which will be restored after the present Block ends.

Clear only operates on the current set of values and thus can be used on a local variable, as in the following basic illustration of a Block:

x = 1;
Block[{x = 2},
Print[x];
Clear[x];
Print[x]
];
Print[x]

(* 2
x
1 *)


In contrast, ClearAll operates on all sets of values stored for the given symbol. In the above example, were ClearAll to be allowed instead of Clear, it would also destroy the original value of x and then it could not be restored.

• Why isn't Remove forbidden for a local variable as well? Sep 8 '16 at 4:51
• Just an implementation choice I guess -- it would be trivial for Remove to do the same check, but it is not present. Removing the symbol entirely is different from removing some or all of its values and flags (not all of which have top level exposure), so this inconsistency does not seem too serious. Sep 8 '16 at 5:23
• Is there a direct way to access these stored previous values? Probably not. Just curious. Sep 8 '16 at 8:11
• @Szabolcs No, not possible from top level (to my knowledge). Sep 8 '16 at 15:43
• In that case we can think of the prohibition against ClearAll to be a rather arbitrary one, I guess. The fact that is there doesn't have any non-obvious practical implications. If we need to clear more than simple definitions, just do it manually for each type of property, i.e. ClearAttributes, etc. Right? Sep 8 '16 at 15:48