LangWart: Method congestion from mutate multiplicty

Rick Johnson rantingrickjohnson at gmail.com
Mon Feb 11 00:59:13 CET 2013


On Sunday, February 10, 2013 5:29:54 AM UTC-6, Steven D'Aprano wrote:
> Rick wrote:
> And you have missed my point, which is that reversed(), and sorted(), were
> not added to the language on a whim, but because they were requested, over
> and over and over again.

Well, well, this explains everything!

We don't add features because of logic, or because of consistency, or even because of good sense, we simply add them to appease the masses.

psst: Steven, maybe if the C and Java heads moan long enough we can get braced scoping, or, if the ruby guys pester us enough we can adopt the dollar sign to denote globals, the "@@" for class variables, and the "@" for instance variables! Oh yes! Because being loved is SO much more important than sticking to our philosophy of the Python Zen.

> "appended" is called list addition.
>
> newlist = oldlist + [item_to_append]

But where is the consistency?

Yes the syntactic sugar of the "plus sign" is concise, however, the "+" operator does not "pair" intuitively with the "append" method. Even IF you transformed the "+" operator into a named method like "add" (or call the magic method "__add__") it still fails to mesh properly with "append", and the two words utterly fail to intuitively establish an "in-place" versus "copy-mutate" relationship. Consider the English definitions of "add" and "append" when applied to sequence objects:

  DEFINE "add"
    Expand a sequence of "somethings" to include
    additional "somethings" -- which may be another
    sequence of N somethings. However the exact
    location of the new "somethings" is not clearly
    intuit-able from the word "add" alone!

  DEFINE "append"
    Expand a sequence of "somethings" to include an
    additional "something". Here the exact location
    is can be intuited as: "at the end".

> >  flatten, flattened
> 
> flatten is another often requested, hard to implement correctly, function.
> The only reason that Python doesn't have a flatten is that nobody can agree
> on precisely what it should do.

Steven, the definition of flatten (as relates to sequences) is very, VERY simple:

    Return a new sequence that is the result of reducing
    a nested sequence of sequences into a single depth 
    sequence.

> Like map, filter, reduce, etc. flatten is not sensibly implemented as a
> mutator method, but as a function.

Only because you, along with a few other high ranking members of this community (including the BDFL himself!) have this /aversion/ to true OOP paradigm. 

Can you provide an example of how flatten "as a method" is incorrect versus flatten "as a function" is correct, or will this challenge be silently swept under the rug as so many before?

> >  insert, inserted
> 
> "inserted" is called addition, together with list slicing when needed.
> newlist = [item_to_insert] + oldlist
> newlist = oldlist[0:5] + [item_to_insert] + oldlist[5:


"inserted" is called "addition" by who?

If are implying that "seq.__add__()" employs the semantics of the English word "addition" and seq.insert(arg) is a thin wrapper around "oldlist[0:5]+[item]+oldlist[5:]", then fine. But how will someone intuit those two methods as have a "mutating pairs relationship" from the names alone? Not to mention that calling magic methods is anti-pythonic!

> >  map, mapped
> >  filter, filtered
> >  reduce, reduced
> 
> Those are nonsense. None of those are in-place mutator methods.

Well not in the current implementation of Python; but they could be if we wanted them to be. Applying mutations both "in-place" and "to a copy" are very helpful. For example, Ruby supplies both forms for many commonly used operations on arrays: (However i am not a fan of these "mutator pairs")

    slice, slice!
    sort, sort!
    flatten, flatten!
    collect, collect!
    map, map!
    uniq, uniq!
    reject, reject!
    reverse, reverse!
    compact, compact!


Steven, just because you have yet to encounter such usage does not mean the usage is "non-sense"

    seq.map(func)
    new = seq.mapped(func)

    seq.filter(lambda x: x<2)
    new = seq.filtered(lambda x: x<2)


> Especially reduce, which reduces a list to a single item. 

Nice to see you are paying attention! I am sure you already know this, although your wording was clumsy and suggests otherwise, but reduce does NOTHING to the list itself:

py> from operator import add
py> a = [1,2,3]
py> reduce(add, a)
6
py> a
[1, 2, 3]

reduce simply returns the result of the reduction; which is an Integer.

However it is my strong belief that the sum function should not exist when a reduce function does. Why? Because "sum([1,2,3])" is the equivalent of "reduce(operator.add, [1,2,3])"; the latter being significantly explicit and the former being a potential linguistical interpretation nightmare.

Now some might complain about this proposed removal of "sum" because the reduce function requires two arguments whereas the sum only needs one, and I say you're correct, however, this negative attribute is an artifact of a "global function nightmare architecture" and IF the core developers of Python would accept the fine principals of true OOP paradigm, then the call would look like this instead:

    seq.reduce(operator.add)

This fine example of OOP style is much easier to grok than the either the sum or reduce global functions could ever wish to be.

> >  extend, extended
> 
> Again, "extended" is spelled list addition.
> 
> Are you sure you've actually programmed in Python before? You seem awfully
> ignorant of language features.

So you are saying that "addition" is a "language feature"(sic). Can you please provide an example of "addition" as a language feature?

py> 'addition' in dir(list)
False

> [...]
> > My point was this: All mutate methods should mutate "in-place",
> 
> Well duh. All mutator methods do mutate in-place, otherwise they wouldn't be
> mutator methods.

So "reversed()" and "sorted()" mutate in-place? Do you realize that these two functions are an extension of the list (or sub-types of list) interface and are in fact mutating a seq object in-place! Maybe not the sequence object you called the function on, but a seq object none-the-less!

> > if the
> > programmer wishes to create a mutated copy of the object, then the
> > programmer should /explicitly/ create a copy of the object and then apply
> > the correct mutator method to the copy.
> 
> Been there, done that, it sucks. That's about a dozen steps backwards to a
> worse time in Python development.

Why? Because you have to type this

    reversed = list(seq).reverse()

Instead of this:

    reversed = reversed(seq)

*rolls-eyes*



More information about the Python-list mailing list