Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > LangWart: Method congestion from mutate multiplicty

Reply
Thread Tools

LangWart: Method congestion from mutate multiplicty

 
 
Rick Johnson
Guest
Posts: n/a
 
      02-11-2013
On Sunday, February 10, 2013 7:30:00 AM UTC-6, Oscar Benjamin wrote:
> On 10 February 2013 04:53, Mark Janssen wrote:
> > [...]
> > I have to agree with Rick, I think requiring the user to explicitly
> > create a new object, which is already a good and widely-used practice,
> > should be the Only One Way to Do It.

>
> Why should I copy a potentially large data structure just to iterate
> over it in reverse order?


That's a good question, and the answer is: "Only a fool would make a copy of ANY data structure only to simply iterate over it; be it forwards or backwards or sideways".

> And why on earth would you want to remove
> the more efficient ways of doing this?


Well these "ways"(sic) might be more efficient, at this time, because the Python developers have defined them to be. This could be changed if they would drop the aversion to true OOP paradigm.

To make this work properly you would need to optimize the constructor of the sequence object. If the user presents the seq object (say for example a list) with variable that points to an already existing list like:

py> a = [1,2,3]
py> for x in list(a).reverse():
.... do_something

Python will not actually create a copy of the list because that would be foolish! Python would instead ITERATE over the existing object transparently. It's called OPTIMIZING CODE! By doing this we gain many things:

* We don't have these foolish "mutate"<->"copy mutate"
method "pairs" like: "seq.reverse()" and
"seq.reversed()"

* We are writing maintainable code by explicitly calling
"Sequence(seq).mutate()". The intent becomes obvious
even though Python may "optimize" our intentions "behind
the scenes".

> > Guessing method names is far suboptimal to this simple, easy idiom.

>
> There is no guessing. If the object has a __reverse__ method then it
> specifically advertises that it knows how to create an iterator that
> gives its values in reverse order. Otherwise __len__ and __getitem__
> are used.


Really.

And you know that simply from intuiting a seemingly unrelated method? Wow, i'd bet the detectives of many municipalities would love to rent some of your powers. What sort of esoteric rule book are you reading from my friend?
 
Reply With Quote
 
 
 
 
Steven D'Aprano
Guest
Posts: n/a
 
      02-11-2013
Rick Johnson wrote:

> 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.


They were requested because people kept re-inventing them. They kept
re-inventing them because they are useful functions that make good sense to
have.


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

>
> But where is the consistency?


Strings use + for concatenation. Tuples use + for concatenation. Lists use +
for concatenation. Seems pretty consistent to me.

Are you sure you've used Python before?


> Yes the syntactic sugar of the "plus sign" is concise, however, the "+"
> operator does not "pair" intuitively with the "append" method.


Adding "ed" to a word does not pair intuitively with the method name. You
have to learn it, which in the case of most English speakers you probably
did between the ages of 2 and 6.

Using + to represent concatenation is no less intuitive.



> 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.


So what?



>> > 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.


Very, VERY simple until you actually implement this function, and discover
that it does too much e.g.

flatten([None, 23, [1, 2, 3], Point(x=2, y=3), ["spam", "ham"]])

=> [None, 23, 1, 2, 3, 2, 3, 's', 'p', 'a', 'm', 'h', 'a', 'm']


So people who have *actually programmed*, instead of just talking about
programming, have discovered that in practice you need to treat some
sequences as primitives that don't get expanded.



>> 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?


Simple efficiency. The most efficient, and sensible, way to flatten a list
is to create a new list. Trying to flatten a list in place is a dumb
idea -- it is O(n**2), or possibly even worse. Since only an idiot would
write flatten as an in-place method, any mutator version of flatten would
have to use a non-mutator version, then use slicing to over-write itself:

def flatten(self):
new_list = flatten(self)
self[:] = new_list


which is fine if you absolutely have to have an in-place version, but why
bother? The caller can do it themselves:

mylist = flatten(mylist)


[snip]
>> > 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.


Now you're smoking crack. How can *reduce* be an in-place mutator method?

py> mylist = [1, 2, 3, 4, 5]
py> from operator import mul
py> reduce(mul, mylist)
120

I would really like to see your implementation of a reduce method that turns
a list into an int *in-place*.



> Applying mutations both "in-place" and "to a copy" are
> very helpful.


Exactly.


[snip]
>> > 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?


No. They are not mutator methods, because they do not mutate in place.


>> > 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()


Are you sure you've programmed in Python before? That gives reversed = None.


--
Steven

 
Reply With Quote
 
 
 
 
Steven D'Aprano
Guest
Posts: n/a
 
      02-11-2013
Rick Johnson wrote:

> On Sunday, February 10, 2013 7:30:00 AM UTC-6, Oscar Benjamin wrote:
>> On 10 February 2013 04:53, Mark Janssen wrote:
>> > [...]
>> > I have to agree with Rick, I think requiring the user to explicitly
>> > create a new object, which is already a good and widely-used practice,
>> > should be the Only One Way to Do It.

>>
>> Why should I copy a potentially large data structure just to iterate
>> over it in reverse order?

>
> That's a good question, and the answer is: "Only a fool would make a copy
> of ANY data structure only to simply iterate over it; be it forwards or
> backwards or sideways".


Aren't you the fool who wants to remove reversed() and have people write:

[quote]
reversed = list(seq).reverse()


Oh yes, you are the fool. And me the bigger fool for listening to you.

Time for another six months in my killfile, methinks.




--
Steven

 
Reply With Quote
 
Mark Janssen
Guest
Posts: n/a
 
      02-11-2013
On Sun, Feb 10, 2013 at 4:10 PM, Steven D'Aprano
<steve+> wrote:
> Mark Janssen wrote:
>
>> A unified data model as I define it, specifies a canonical atomic unit
>> (like the unit integer) and an abstract grouping construct in which
>> these atomic units can be arranged. By themselves, these two can
>> construct arbitrary levels of data structure complexity. Add the
>> ability to apply names to these levels, and you have a complete data
>> model for a happy programming environment. My work, to give you some
>> context, involves the invention of a "fractal graph" which is where
>> the name "unified object model" came from, because a fractal graph, I
>> argue can represent every part of the physical world at every scale.

>
> How can you breathe *way* up there in space?
>
> http://www.joelonsoftware.com/articl...000000018.html


Haha, point taken, but I actually have an application for such a
high-level abstraction -- a 3-d web. A unified information model
could take the internet to the next level (much like the Internet
itself did to all the disparate communications networks before).
Instead of the current hypertext and cumbersome attempt at coding
semantic meaning in RDF tags, (re)present the internet content in a
3-d space and let the visual cortex, along with the crowd, make the
relationships. (See pangaia.sourceforge.net)

> P.S. not all phenomena are fractal. The elbow joint, for instance, is just a
> hinge, and not made of smaller elbow joints made of tinier elbow joints
> made of even tinier elbow joints made of ...


Oh, no doubt about that. Perhaps instead of fractal graph, I should
call it a recursive graph -- there must be a "base case" which ends
the infinite regress. For the model I've been working on, that base
case is the unit integer (or the machine word with only the
least-significant-bit set to "1").

Cheers,

mark
>
>
> --
> Steven
>
> --
> http://mail.python.org/mailman/listinfo/python-list

 
Reply With Quote
 
Rick Johnson
Guest
Posts: n/a
 
      02-11-2013
On Sunday, February 10, 2013 6:12:57 PM UTC-6, Tim Chase wrote:
> What should you get if you flatten
>
> [[[1,2],[3,4]],[[5,6],[7,8]]]
>
> Should the result be
>
> [[1,2],[3,4],[5,6],[7,8]]
>
> or
>
> [1,2,3,4,5,6,7,8]
>
> I've needed both cases, depending on the situation.


Well providing /every/ possible solution for /every/ possible answer to /every/ problem is not going to be possible unless you are willing to endure an endless amount of complexity.

My opinion is that flatten should should call seq.flatten() on all sub-sequences. That seems like the only /reasonable/ resolution to allow. At least sub-types could define how they get flattened.

However, that does not solve your problem: where you wish to flatten a sequence down to a prescribed sub-depth; in your example: flatten(subdepth=1)..

class Sequence():
"""Hypothetical sequence object."""
def flatten(self, depth=INFINITY):
# ...

py> seq = [[[1,2],[3,4]],0,[[5,6],[7,8]]]
py> seq.flatten()
[1,2,3,4,0,5,6,7,8]
py> seq.flatten(depth=1)
[[1,2,3,4],0,[5,6,7,8]]
py> seq.flatten(depth=2)
[1,2,3,4,0,5,6,7,8]
py> seq.flatten(depth=3)
# Throw error or just quietly return flat list???

I don't feel very good about this API though. But i admit it might be beneficial to some folks. Should this example be the built-in behavior of Sequence#flatten, probably not. But hey, here at pydev we add features that appease the masses because we want to be loved. So folks, get your votes in!
 
Reply With Quote
 
Rick Johnson
Guest
Posts: n/a
 
      02-11-2013
On Sunday, February 10, 2013 6:12:57 PM UTC-6, Tim Chase wrote:
> What should you get if you flatten
>
> [[[1,2],[3,4]],[[5,6],[7,8]]]
>
> Should the result be
>
> [[1,2],[3,4],[5,6],[7,8]]
>
> or
>
> [1,2,3,4,5,6,7,8]
>
> I've needed both cases, depending on the situation.


Well providing /every/ possible solution for /every/ possible answer to /every/ problem is not going to be possible unless you are willing to endure an endless amount of complexity.

My opinion is that flatten should should call seq.flatten() on all sub-sequences. That seems like the only /reasonable/ resolution to allow. At least sub-types could define how they get flattened.

However, that does not solve your problem: where you wish to flatten a sequence down to a prescribed sub-depth; in your example: flatten(subdepth=1)..

class Sequence():
"""Hypothetical sequence object."""
def flatten(self, depth=INFINITY):
# ...

py> seq = [[[1,2],[3,4]],0,[[5,6],[7,8]]]
py> seq.flatten()
[1,2,3,4,0,5,6,7,8]
py> seq.flatten(depth=1)
[[1,2,3,4],0,[5,6,7,8]]
py> seq.flatten(depth=2)
[1,2,3,4,0,5,6,7,8]
py> seq.flatten(depth=3)
# Throw error or just quietly return flat list???

I don't feel very good about this API though. But i admit it might be beneficial to some folks. Should this example be the built-in behavior of Sequence#flatten, probably not. But hey, here at pydev we add features that appease the masses because we want to be loved. So folks, get your votes in!
 
Reply With Quote
 
alex23
Guest
Posts: n/a
 
      02-11-2013
On Feb 9, 2:51*pm, Chris Angelico <ros...@gmail.com> wrote:
>> Rick Johnson <rantingrickjohn...@gmail.com> wrote:
>> I really don't like to read docs when learning a language,
>> especially a "so-called" high level language. I prefer to learn
>> the language by interactive sessions and object introspection. Then,
>> when i have exhausted all abilities to intuit the solution, i will
>> roll my eyes, maybe blubber an expletive, and then reluctantly crack
>> open a user manual.

>
> What Rick means: "I want to claim that I've learned a new language,
> but I want it to work exactly like the imaginary language in my mind,
> and if it doesn't, I'm going to complain about it, rather than,
> yaknow, actually learn a new language."


Yeah, this is, pardon the french, just batshit crazy. How does one
_ever_ learn _anything_ new if they expect everything to conform with
their pre-established intuitions?

As can be seen by his posts, the outcome is one just _doesn't_ learn.


 
Reply With Quote
 
MRAB
Guest
Posts: n/a
 
      02-11-2013
On 2013-02-11 00:36, Steven D'Aprano wrote:
> Rick Johnson wrote:
>
>> 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.

>

I remember a time when he was saying that the developers of the
language were ignoring the silent majority. Now he's saying that we
shouldn't simply add things to appease the masses.

> They were requested because people kept re-inventing them. They kept
> re-inventing them because they are useful functions that make good sense to
> have.
>

Exactly.

Practicality beats purity, and all that.



 
Reply With Quote
 
alex23
Guest
Posts: n/a
 
      02-11-2013
On Feb 11, 9:59*am, Rick Johnson <rantingrickjohn...@gmail.com> wrote:
> 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.


When "logic" or "good sense" are writing programs, maybe then we'll
listen more to what they want in a language.

"Good sense" would dictate that someone actually read documentation
when dealing with a new programming language. "Logic" would indicate
that expecting things outside of your control to confirm with your
intuition is a fool's game; I highly recommend not reading up on any
modern physics as there'll be plenty there that just makes you angry.

PS pragmatism is a perfectly valid philosophical approach too. Far
more practical than more "pure" approaches, and something something
foolish consistency blah blah small minds.
 
Reply With Quote
 
Mark Lawrence
Guest
Posts: n/a
 
      02-11-2013
On 11/02/2013 02:05, alex23 wrote:
>
> I highly recommend not reading up on any
> modern physics as there'll be plenty there that just makes you angry.
>


Spoil sport. Fancy not wanting rr's views on string theory

--
Cheers.

Mark Lawrence

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: LangWart: Method congestion from mutate multiplicty Jean-Michel Pichavant Python 0 02-11-2013 09:52 AM
Re: mutate dictionary or list Bruno Desthuilliers Python 0 09-07-2010 01:55 PM
mutate an object or create a new one? toton Java 23 11-02-2006 01:37 PM
naming convention for functions that mutate their arguments? mike p. Python 1 02-27-2004 02:18 AM
how to mutate a tuple? Carlo v. Dango Python 10 10-14-2003 03:32 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57