6

In Wolfram Language, Import["file.wl"] can import external wolfram package, Is it reversible?

Can I unimport some packages? In other means Unset all the Function, Variable which is Set when Import?

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
  • This sounds like an XY problem http://xyproblem.info/ There may be a good reason to want to unload a package, but I cannot think of one. What's your actual problem? – Szabolcs Jun 17 '20 at 07:45
  • Can you clarify the question please, and explain what you are trying to achieve by "unimporting"? – Szabolcs Jun 17 '20 at 12:26

2 Answers2

7

The correct way to load a package is Needs or Get, not Import.

No, loading is not reversible. The only way to restore the pre-package-loading state robustly is to restart the kernel with Quit.

Alternatively, you may remove the package's context from the $ContextPath. This will effectively hide the package's symbols. However, this does not unload the package. The package's symbols will still be usable, but they must be referred to with the full context.

In other means Unset all the Function, Variable which is Set when Import?

Note that loading a package may do a lot more than create definitions. Clearing definitions is not a safe way to "unload" it.

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
  • One potentially useful purpose might be for testing or resolving namespace collisions without using Quit[]. – Rolf Mertig Jun 17 '20 at 08:51
  • @RolfMertig Yes, that's a good use. However, in that case the solution is to remove the context from the $ContextPath, not to try to clear definitions. – Szabolcs Jun 17 '20 at 09:27
  • @Szablcs What if you want to cleanly reload a package while developing it? Using Get again is not always enough. And I somehow don't like to Quit and restart the kernel. Too slow. As so much ... – Rolf Mertig Jun 17 '20 at 11:23
  • @RolfMertig That's not what the OP was asking though. It may be what they wanted, but it's not what they asked. This is why I said it looks like an XY problem. The Import thing makes it even more unclear. Some context is needed from the OP. – Szabolcs Jun 17 '20 at 11:38
  • @RolfMertig When faced with a question with this, and the OP does not clarify (as here), there is no ideal solution. One can answer literally, as I did ("it is not possible to unload") or one may start guessing at what OP really wanted. That guesswork can be a waste of time, is likely not the best solution anyway for the OP's actual problem, and in the worst case the answer may end up being copied again and again and completely misused in outright dangerous ways. – Szabolcs Jun 17 '20 at 11:45
  • I agree. BTW: Isn't Import["package.wl"] exactly identical to Get["package.wl"] (except $Path dependencies, i.e., Import@FindFile@"ComputerArithmetic\"does the same asGet@"ComputerArithmetic`"`) ? – Rolf Mertig Jun 17 '20 at 11:45
  • @RolfMertig Well, Import appears to work, but it's not designed for this ... so we shouldn't use it for this, or risk subtle things breaking. Is there any reason to use it? OP is probably coming from Python and misundesrstood what Import does. I think the main argument against is that it is not designed for this purpose. Who knows what can go wrong? – Szabolcs Jun 17 '20 at 11:51
  • Things I know about: 1) in not-so-old versions Import could not be safely used in init.m (I think this was fixed) 2) Import has high overhead (ok, not a big deal) 3) Import determined the FileFormat partially based on the first few bytes, and not solely based on the file extension. Is it guaranteed that it will always load it was a "Package" and not as some other import format? 4) Something I suspected might go wrong, but didn't: does it load new-style packages correctly? (It turns out, it does.) – Szabolcs Jun 17 '20 at 11:53
3

If a package only consists of definitions, does not load subpackages and does not attach the Locked attribute to its symbols, then it is possible to remove its definitions by

unLoad[context_String /; StringEndsQ[context, "`"]] := (
  Unprotect; (Unprotect[#]; Remove[#]) & /@ {context <> "*", 
    context <> "*`*"}; $ContextPath = 
   DeleteCases[$ContextPath, context];
  )

This can be tested by, e.g.,

 Needs["ComputerArithmetic`"];
 unLoad["ComputerArithmetic`"];

Now Names["ComputerArithmetic`*"] gives an empty list

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
Rolf Mertig
  • 17,172
  • 1
  • 45
  • 76