Ethan Furman ethan at stoneleaf.us
Thu Feb 10 11:52:38 EST 2011

```Jason Swails wrote:
> On Wed, Feb 9, 2011 at 8:16 PM, Ethan Furman wrote:
>     while n:  is plenty readable.  n is either something or nothing, and
>     something evaluates to True, nothing to False.
>
> Sure it's readable.  But then you have to make sure that the loop will
> eventually take n down to 0.

Sure, but the same holds true with 'while n != 0' -- you have to make
sure the loop will eventually take n down to 0.

> You can always *assume* that the
> programmer knew what they were doing (not an assumption I'm typically
> willing to make on code that's not my own).

Hopefully not something you have to deal with unless you're debugging...

> How is "while n != 0:" any worse?  (or abs(n) < tolerance).  It has
> exactly the same effect without adding any code while at the same time
> directly communicates the intended conditional.  IMO it makes reading
> the code easier to read barring effective documentation (my experience
> with people documenting their code is that they don't; at least in my
> field).  "while n != 0" makes my life easier.

In that instance (a bunch of mathematical functions), I can easily see
using that construct.

> The fact that the proposed loop finished with *nothing* was
> coincidental.  What if he had been doing some type of prime
> factorization or something where each iteration reduced the number until
> eventually all you were left with was the multiplicative identity?
> You'd say (correctly) that obviously the same approach won't work, but
> in some lines of thought it's a logical extension to use the same
> construct (especially to those that don't fully understand why the
> original loop exits in the first place).  Expanding the conditional a
> little can only help IMO.

Thank you for making my argument for me -- you have to understand the
tool you are using to make the best use of it.

>         def num_digits(n):
>           return len(str(n).replace('-','').replace('.',''))
>
>         Or typecast to an int if you want to neglect decimals before
>         converting to a string, etc.
>
>         Or use recursion!
>
>          >>> def num_digits(n):
>         ...    if n == 0:
>         ...       return 0
>         ...    else:
>         ...       return num_digits(n//10) + 1
>         ...
>          >>> num_digits(1)
>         1
>          >>> num_digits(0)
>         0
>
>
>     0 is still one digit.  ;)
>
>
> Well that is something; yet only nothing evaluates to False.  We seem to
> be at an impasse :).

I fail to see how a faulty algorithm puts us at an impasse.  To tweak

--> def num_digits(n, _first_pass=True):
-->     if n == 0:
-->         return int(_first_pass)
-->     else:
-->         return num_digits(n//10, _first_pass=False) + 1

correctly handles the special case of zero.  To use my style, it would
look like:

--> def num_digits(n, _first_pass=True):
-->     if n:
-->         return num_digits(n//10, _first_pass=False) + 1
-->     else:
-->         return int(_first_pass)

And, of course, this only works for non-negative integers.  (I'll leave
the discussion of whether zero is non-negative to others.  ;)  As I said
earlier, I can see using the 'if n == 0' construct in certain
situations, and if the non-zero branch were lengthy I would stick with
the first version here.

~Ethan~

```