I was working on an answer to this question, when I was sidetracked by what I bring up here.
I wanted a function, which when given a string representing a binary number, would convert the string to a list of digits. I wanted to reject any invalid strings and to return the function expression unevaluated an invalid string was rejected.
I had a lot of trouble debugging the function. My edits to the function body didn't seem have any effect. Finally, in desperation, I got to performing Clear[bitsToDigits]
before making an edit. This allowed to complete my debugging, but left me very puzzled because I have come to expect edits which don't effect the first argument of a SetDelayed
not to require clearing the function's identifier. In such cases, I have come to expect evaluating SetDelayed
to replace the old down-value with the new one.
I decided to look at the down-values after making a second definition of now working function, but not to clear before evaluating it.
bitsToDigits[bitstr_String] :=
With[{result =
Module[{valid, bits = Characters[bitstr]},
valid = StringFreeQ[bitstr, Except["0" | "1"]];
If[valid, bits, False, False]]},
result /; result =!= False]
bitsToDigits[bitstr_String] :=
With[{result =
If[StringFreeQ[bitstr, Except["0" | "1"]],
Module[{bits = Characters[bitstr]}, bits], False, False]},
result /; result =!= False]
I now looked at the down-values
DownValues[bitsToDigits]
To my horror, the result was
{ HoldPattern[bitsToDigits[bitstr_String]] :> With[{result = Module[{valid, bits = Characters[bitstr]}, valid = StringFreeQ[bitstr, Except["0" | "1"]]; If[valid, bits, False, False]]}, result /; result =!= False], HoldPattern[bitsToDigits[bitstr_String]] :> With[{result = If[StringFreeQ[bitstr, Except["0" | "1"]], Module[{bits = Characters[bitstr]}, bits], False, False]}, result /; result =!= False] }
The new version of my function will never be executed because the older definition will always match first.
This was totally unexpected. Should I have expected this? Is there something wrong with my definitions of bitsToDigits
? If so, how should I fix them? Or have I found a bug?
I have verified that my problem occurs in both V9 and V10 running on OS X.
update
Mr.Wizard has answered my question as originally posted, but I would be keen to learn if there is a way to implement the behavior I want without the distressing side effect, which interferes with my ingrained code development habits.
The new version of my function will never be executed because the older definition will always match first
it should really have kept only the last one? !Mathematica graphics yes, this is very strange. $\endgroup$Condition
. $\endgroup$Condition
you had there, since it was at the bottom of the body, I never saw condition put there! $\endgroup$Condition
has very special behavior when used that way. Please see the middle of this answer for an explanation in my own words: (1852) $\endgroup$