10
$\begingroup$

I have a pretty robust workflow for developing in Notebooks. One element of that workflow is the reflexive habit of saying ClearAll just before a definition so that experimental definitions don't linger and fool me during iterative, interactive development. For example, suppose I define

foo[x_] := bar[x];

and then later, I decide to change the definition. I overwrite the above with

foo[xs___] := baz[xs];

naively expecting foo to forget about bar. But I get a surprise. While foo[1, 2] produces baz[1, 2], foo[1] produces the old bar[1]. If I had written

ClearAll[foo];
foo[x_] := bar[x];

and

ClearAll[foo];
foo[xs___] := baz[xs];

I wouldn't have had the surprise. Obviously, this can be really important in big, complex definitions with many cases and branches all intertwined and infeasible to track in your head, so it's a routine habit and I don't even think about it any more.

The question is whether the same habit should pertain to Package development. I never see ClearAll before definitions in the Packages I've read, but wouldn't it make sense for the same reason as it does in Notebooks? Or is there some other development fu technique that I don't know about for Packages? Or do people only publish completely finished, formally certified & debugged Packages, and they never need to do iterative development on them ever again (tiny sarcasm)? Or, is there special magic in the Package system that clears symbols on a package reload? Perhaps the subcontexts are automatically discarded?

In short, why don't I see ubiquitous ClearAll in Packages?

$\endgroup$
  • 2
    $\begingroup$ In packages, all symbols should be localized to the package context, then you can clear the whole context in one go instead of having to clear definitions one by one. Some packages have it at the beginning. $\endgroup$ – Szabolcs Jul 20 '15 at 17:48
  • 2
    $\begingroup$ FWIW, I keep ClearAll in my packages, even in production code. I can't see how this can possibly hurt, while this leaves me an option to not clear certain symbols, for example because they receive their definitions in more than one file (which doesn't often happen, but sometimes does, and can not always be easily avoided). $\endgroup$ – Leonid Shifrin Jul 20 '15 at 21:37
5
$\begingroup$

When using automatically generated packages I am selective about which Cells I mark for Initialization and therefore transference to the package file. I don't find the need to include ClearAll in such cases. I do use a Unprotect / Protect paring which at least prevents additional definitions from accidentally being made elsewhere.

A case where ClearAll might be undesirable is memoization; one may want to be able to forcefully reload the package (Get) without losing existing memoized values. (This contravenes direct use of Protect however.)

$\endgroup$
  • $\begingroup$ If I read your first paragraph correctly, you're exercising a Package-development fu technique where you develop in Notebooks, create packages by automatic generation (reference, please?), and seldom if ever edit the .m package file directly? $\endgroup$ – Reb.Cabin Jul 20 '15 at 16:32
  • $\begingroup$ @Reb.Cabin That is correct. Let me see what documentation I can find. $\endgroup$ – Mr.Wizard Jul 20 '15 at 16:34
  • 1
    $\begingroup$ @Reb.Cabin For documentation I linked to a question, which I just realized you asked. There is also (2202). $\endgroup$ – Mr.Wizard Jul 20 '15 at 16:38
  • 2
    $\begingroup$ LOL -- i guess there are many kinds of leaks -- evaluation leaks, resource leaks, MEMORY leaks :) $\endgroup$ – Reb.Cabin Jul 20 '15 at 16:50
  • 1
    $\begingroup$ Oh, duh. Not only forgetful am I, but blind, too :) $\endgroup$ – Reb.Cabin Jul 21 '15 at 16:12
4
$\begingroup$

I found, in the "Applications" section of the documentation of ClearAll, this authoritative recommendation:

Unprotect and clear all symbols in a package, to allow it to be read twice:

Begin["`Private`"];

Unprotect["`*"]; 
ClearAll["`*"];

f[x_] := x^2

Protect[f];

End[];

I don't see this advice in the guide here for Setting up Wolfram Packages, which seems a small shame.

$\endgroup$
  • $\begingroup$ I cannot recall reading that, but I probably have. Thanks for bringing this to my attention. I do not necessarily read that line as commanding, but declarative, explaining the code below. A somewhat odd example though as I don't believe the ClearAll will change anything there. $\endgroup$ – Mr.Wizard Jul 26 '15 at 10:56
  • $\begingroup$ Wouldn't the ClearAll have the declared effect if the package were read in twice? By the way, somewhere in the Wolfram docs there was a package example with Begin["Private`"] instead of Begin["`Private`"], which would seem to cause all kinds of mayhem (crosstalk amongst packages). I couldn't find it again, else I would have written an SE question about it. $\endgroup$ – Reb.Cabin Jul 26 '15 at 12:38
  • $\begingroup$ What I meant is that only in select cases will ClearAll actually be needed; normally evaluating the definition code again on top of the existing definitions usually works just fine. In this case you can run Do[f[x_] := x^2, {1000}] and it's just the same when it gets done. It would have been better, IMHO, to give an example where the ClearAll was needed and without it the definitions failed. Although now that I'm writing this I suppose it would be "good practice" to throw in a ClearAll just in case. $\endgroup$ – Mr.Wizard Jul 26 '15 at 12:57
  • $\begingroup$ I see. Yes, the ClearAll is most useful during development when one is rapidly changing the architecture of an API --- the various patterns you want your rules to match. That's where you get bitten by the implicit system-rules that can reorder your rules, and your lingering rules that don't get eliminated when you broaden or sharpen patterns. $\endgroup$ – Reb.Cabin Jul 26 '15 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.