It is illustrative to compare Block
, Internal`InheritedBlock
, Module
, and With
. Both Module
and With
create unique versions of the variables which are not accessible from the outside (lexical scoping, and not without its issues), e.g.
x = 2 y^2 - 7;
With[{y = 5}, x]
Module[{y = 5}, x]
where both With
and Module
return -7 + 2 y^2
. With
has the added ability to bypass Hold
attributes, which is very useful sometimes. Because of this, it would be difficult to use them to run arbitrary code passed in by a user. In contrast, Block
and Internal`InheritedBlock
allow you to temporarily augment/overwrite an existing variable, and guarantee that the changes are reset.
A useful example of augmentation, is automatically resetting changes made to default Options
, e.g.
Internal`InheritedBlock[{Plot},
SetOptions[Plot, PlotStyle -> {Red, Blue, Green}];
Options[Plot, PlotStyle]
]
(* {PlotStyle -> {Red, Blue, Green}} *)
vs
Options[Plot, PlotStyle]
(* {PlotStyle -> Automatic} *)
which can be used to generate many plots where the options are uniform, without resorting to crafting a unique theme. A more interesting example is this graphics parser which uses Internal`InheritedBlock
to mimic a stack in tracking the state. If you want a more extensive augmentation, though, you still need to Unprotect
the symbol. This is where Block
comes in as quite often you do not want to just augment the behavior, but overwrite it entirely.
This is the use case for Plot
, Table
, etc. where the user supplies a symbol/expression that needs to be evaluated without worrying about whether it has *Values
. Internal`LocalizedBlock
extends this further by localizing things like Subscript[x, 1]
which Block
cannot handle.
Of course all these can be merged. Consider this answer from Leonid which traces what packages auto-load another package. It uses Module
to set up a closure which uses the Villegas-Gayley pattern to augment Needs
. Here Block
plays the important role of blocking recursive execution.
SetAttributes[x, Protected]; Table[x, {x, 2}]
? $\endgroup$Block
, isn't it? Or is your question whyTable
is based onBlock
? $\endgroup$OwnValues
, check outInternal`LocalizedBlock
. $\endgroup$Internal
InheritedBlock` perhaps. $\endgroup$*Values
that remain. :) $\endgroup$