Implicit conversion to boolean in if and while statements

Rick Johnson rantingrickjohnson at gmail.com
Sun Feb 10 01:25:55 EST 2013


On Friday, February 8, 2013 7:06:34 PM UTC-6, Ian wrote:
> On Fri, Feb 8, 2013 at 12:58 PM, Rick Johnson
>  wrote:
> > I'm a bit unnerved by the sum function. Summing a
> > sequence only makes sense if the sequence in question
> > contains /only/ numeric types. For that reason i decided
> > to create a special type for holding Numerics.
> > [...]
> > Of course someone could
> > probably find a legitimate reason to apply a sum method
> > to non-numeric values; if so, then inherit from
> > NumericSequence and create your custom type!
>
> Are you aware that the approach you're advocating here is bad OOP
> design?  If you declare a class NumericSequence with the property that
> it contains only numeric types, and then you declare a subclass
> NonnumericSequence that does not share that property, then guess what?
> You've just violated the Liskov Substitution Principle.

I totally agree! Really, no sarcasm here O:-)

Not only because we would be attempting to bend a numeric type into something it is not, but even more foolishly because the very method we hope to gain (sum) would need to be completely re-written anyway. I must have lost myself in the rant because that was a foolish thing to say. Thanks for pointing this out.

> The goal you're trying to achieve here is nonsensical anyway.  Ask
> yourself what the semantic meaning of the sum() function is, what
> purpose it is meant to serve.  My answer: it is the reduction of the
> addition operator.

I think that for Numeric Types your answer is spot on! And i'll bet if we ruminated long enough we could probably find a few more transformations of the word "sum" into unique contexts. But i digress, we'll have to save that synergy for a time when you are buying the beer! ;-)

> The implication of this is that the input type of
> the sum() function is not "numbers", but rather "things that can be
> added".

Indeed. Contrary to what a few folks have stated in this thread, if two different objects have methods named "sum", that does NOT mean that we have broken the fine principles of "code reuse", no. Why? Because two methods named "sum" can contain completely different code! Yes, i know that's difficult for some to believe, but it's the truth!

Consider a sum method of a "Numeric Type" compared to the sum method of a "Sequence Type". Not only is the algorithm different, but the result is different. Summing N numerics requires utilizing the strict rules of mathematical addition, keeping a running total, and returning a type (Integer) that is different from the input type, whereas summing sequences requires expanding the first sequence with the values of the second sequence (all whilst maintaining linear order) and returning a new instance of the same type (f.e. list). 

Of course you could write a single monolithic function that can operate on multiple types transparently (*cough* saum!) however:

 * Nobody can predict the future (at least not yet) so you
   will eventually encounter a new type that breaks the
   god @#$% function.

 * Your language will rely on "magic", thereby confusing
   it's users, with well, magic!

 * But most disappointing of all: you will break the accepted
   OOP convention of encapsulation, whereby the object
   /itself/ should operate on the data, not some outside god
   @#$% function!

But let's dig a little deeper here so we might understand /why/ encapsulation is /so/ gawd @#$%ed important to OOP. 

Why do we prefer objects to operate on their own data rather than some "magical-all-knowing-god-like-creature-from-another-planet-who-thinks-his-bowel-movements-smell-like-bakery-fresh-cinnamon-rolls? Is it because we want objects to feel a sense of "belonging" or "importance"? ...OF COURSE NOT! Objects neither think nor feel!

We employ encapsulation because by doing so we keep all the relevant code under one class, one module, one package. By doing so we create a hierarchy; and since hierarchies are much easier to search than random sequences, we will thank ourselves later!

If you want a fine example of this consider a list and a dict object. If you want to find a value in a list you are forced to search the entire list "item-by-item" until you find a match; there are NO shortcuts here! However, when we have data in a dict all we need is a key, and voila!, we have a direct path to the item! Same applies to code.

RR: "GOOD paradigms solve problems when /writing/ code, GREAT paradigms solve problems when writing and /maintaining/ code!"

> That includes numbers, but since I see from your proposed
> class hierarchy that you are retaining the __add__ method on
> sequences, it also includes sequences.  Are you really going to tell
> the user that (1, 2, 3) + (4, 5, 6) is perfectly fine, but that the
> semantic equivalent sum([(1, 2, 3), (4, 5, 6)]) is nonsense?

Yes. Because if the user has a problem understanding /why/ adding two sequences together results in a new sequence and /not/ a number, he can simply open the source for the Sequence object, locate the sum method, and read code that is ONLY RELEVANT TO SUMMING A SEQUENCE OBJECT. [1]

Whereas with a global function --which has been whored-out to operate on many types, and will probably include a massive conditional!-- he will need to read through many lines of irrelevant code just to find the relevant code, then /hopefully/ he has the cognitive power remaining to find the answer.

[1] Of course this is not the /only/ reason why encapsulation is so important.



More information about the Python-list mailing list