I have been using Mathematica for about 2 years and I'm pretty ok to write and optimize my code. Wanting to improve my practice, I often look at code examples. However, I can not determine if there is a "good way to do" with the use of functions Clear
, ClearAll
and other related functions (as Remove
). I note that several people clear all at the beginning of each code, while other clear only the variables. So what would be a good practice?
2 Answers
I'd like to summarize the discussion that took place in comments, since I think this is an important question, and a common source of frustration when lingering definitions cause weird behavior that can be confusing to less experienced users. Once answered (and maybe expanded), hopefully this question could be used as a target for closure as duplicate.
Stylistically I personally like to at least apply Clear
or perhaps ClearAll
to the name of a new function defined with SetDelayed
right before its definition(s). This helps me prevent lingering definitions, which are hard to debug.
On the other hand, I typically do not bother clearing the values of symbols before simple assignments with Set
(i.e. =
), since any existing values (OwnValues) will be overwritten.
Notice also that, as Kuba mentioned, "Clear
does not clear attributes, messages, or defaults associated with symbols.", whereas ClearAll
does. (The passage is from the documentation of Clear
).
Physicien then wondered about the Remove
function, to which andre contributed a specific case in which Remove
can be handy. If you mistakenly reference a symbol from a package before loading the package, that symbol will be created, typically in the Global`
context, or whatever the default is in your current notebook. If you then load the package, you will run into shadowing issues, i.e. the same symbol appears in two contexts, the current one generated by your premature use, and the package one. In that case, Remove
is useful to remove the superfluous symbol.
Actually I think "good practice" would be to try to write code which would make the use of Clear
, ClearAll
or Remove
unnecessary. If either of them is necessary that means some of the code that was run before has left the Kernel in an undesirable state. In many cases the origin is as simple as symbols which should have been localized but were not.
The common practice to Clear
or ClearAll
as first statement in many answers on this site is IMO just to avoid unexpected side effects due to old definitions from previous tries to solve the problem in the question, with a high probability of having made definitions for the same symbol (names). I would not consider that to be a suggestion to start code like that in general. It rather should be seen as a result of the fact that you change the state of the Kernel with every definition you make and only if the Kernel is in a well defined state (knows the correct definitions) you can be sure your code will behave as you expect.
To Clear
symbol definitions before making function definitions is mainly useful during development to wipe out the previous deficient definitions from the last try, again the goal is to guarantee a "well defined state" for your next try. If you find it to be necessary in the final "production" code that has IMHO a smell that something is wrong with the code.
As usual there are exceptions from that rule, but you really should need a Clear
rarely -- in exceptional situations.
On the other hand typical use cases of Mathematica are the process of trying out and developing code, where a Clear
for the next try of course makes sense. I personally prefer to frequently Quit
the kernel completely which doesn't really take that long on a modern computer and then load a package file with all my current definitions. That will much more guarantee a well defined state than trying to get into such a state by Clear
or ClearAll
exactly those symbols that are necessary for the state you strive for. Another strategy I use nowadays is to write code so that I can load the next version of my code completely into a new namespace (Context
) and leave the last version in another. That way I can even run direct comparisons. But that is admittedly a rather advanced and maybe exotic approach and not something I'd suggest in general...
-
3$\begingroup$ Albert, I understand and appreciate your point of view. However, as you mention yourself, the great value of Mathematica to the non-programmer is precisely in the fact that I can get stuff done while not having to worry too much about "good programming practices" and "production code". As a practicing chemist, I have been using Mathematica for some time now, but never built a package: my "coding" often has to do with loose notebooks and one-offs. That's the perspective I tried to expose in my summary answer. I'm glad that you contributed an alternative point of view. $\endgroup$– MarcoBCommented Jun 2, 2016 at 5:06
-
1$\begingroup$ I absolutely know that my perspective only covers some probably not so common use cases of mathematica. But as the OP has asked explicitly for good practices I couldn't resist to at least give that point of view. I think this is a great example why it is valuable that there can be more than one answer to a question. I would also suggest that the OP should keep yours as the accepted answer as it has more practical value for most users. I hope with the additional information in mine some of them will recognize anti-patterns in their usage of that functionality... $\endgroup$ Commented Jun 2, 2016 at 14:07
ClearAll
should be a good habit $\endgroup$Clear
or perhapsClearAll
the name of a new function defined withSetDelayed
right before its definition(s), to try and prevent lingering definitions, which are hard to debug. I typically do not bother clearing the values of symbols before simple assignments withSet
, since they will be overwritten. $\endgroup$Remove
function, I wonder if there are cases where this function is better. $\endgroup$Remove
is usefull when I want to use a symbol from a package but have forgotten to load the package. Then the symbol created by the first call of the symbol (typically in the context Global) shadows the symbol in the context of the package. In this case, one mustRemove
the symbol. That's my unique use ofRemove
$\endgroup$Remove
may create rubbish: mathematica.stackexchange.com/q/4921/1871 $\endgroup$