14

I do not understand this behavior:

method[args_] :=
    (* forget the context path *)
    Block[{$ContextPath},
            (* should given nothing, right? *)
         Print["cpath=", $ContextPath];
            ...

but when evaluated it gives the full context path (i.e. it does not forgets it). Why is that? This is against everything I (seem to) know about the Block function.

Sjoerd C. de Vries
  • 65,815
  • 14
  • 188
  • 323
zorank
  • 829
  • 4
  • 14

2 Answers2

13

There are some "special variables" in Mathematica that cannot be cleared. These are fundamentally necessary for its operation and while it will let you revert to a default value inside a Block, it will not allow you to clear it.

You can verify this directly, without Block:

Clear@$ContextPath

Clear::spsym: Special symbol $ContextPath cannot be cleared. >>

It doesn't work even though $ContextPath is not Protected or Locked.


You can find out which other symbols are special:

Reap[Quiet@Check[Clear@#, Sow@#, Clear::spsym] & /@ 
    Select[Names["System`*"], FreeQ[Attributes@#, Protected] &]] // Last // Last

(* {$ActivationGroupID,$ActivationKey,$ActivationUserRegistered,$AssertFunction,$Assumptions,
 $BatchInput,$BoxForms,$CharacterEncoding,$Context,$ContextPath,$HistoryLength,$InputFileName,
 $InstallationDirectory,$IterationLimit,$Language,$LicenseExpirationDate,$LicenseID,
 $LicenseProcesses,$LicenseServer,$LicenseSubprocesses,$LicenseType,$LoadedFiles,
 $MachineAddresses,$MachineDomain,$MachineDomains,$MachineID,$MachineName,$MaxExtraPrecision,
 $MaxLicenseProcesses,$MaxLicenseSubprocesses,$MaxPiecewiseCases,$MaxPrecision,$MaxRootDegree,
 $MinPrecision,$ModuleNumber,$NetworkLicense,$NumberMarks,$ParentLink,$ParentProcessID,
 $PasswordFile,$PatchLevelID,$Path,$ProcessID,$RandomState,$RecursionLimit,
 $TemporaryDirectory,$TemporaryPrefix,$TopDirectory,$TraceOff,$TraceOn,$TracePattern,
 $TracePostAction,$TracePreAction,$UserBaseDirectory,$UserName} *)

From a quick look at what's in the list, you can easily see that most of these are critical for the software to function.

rm -rf
  • 88,781
  • 21
  • 293
  • 472
12

If I try this, everything gets removed except for {System`,Global`}:

In[1]:= $ContextPath

Out[1]= {"PacletManager`", "QuantityUnits`", "WebServices`", "System`", "Global`"}

In[2]:= Block[{$ContextPath}, Print[$ContextPath]]

During evaluation of In[2]:= {System`,Global`}

My guess is that this is a special exception which is implemented to make $ContextPath usable like this:

Block[{$ContextPath}, Needs["SomePackage`"]]

This loads the package without adding it to the context path. It's quite useful with Combinatorica in version 8 and later.

It is in fact possible to remove System` and Global` from $ContextPath but this just breaks the system completely and would also make it impossible to load any packages. You can (in a new session, where you won't lose work!!) try $ContextPath = {} and render the system unusable if you are using a notebook interface. The reason why package loading would be broken is that System` context symbols would need to be referenced by the full name, as in System`Sin, which packages don't do.

So I think this is a special exception to the behaviour of Block/$ContextPath that makes the above use case possible.

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263