Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #38490 > unrolled thread

LangWart: Method congestion from mutate multiplicty

Started byRick Johnson <rantingrickjohnson@gmail.com>
First post2013-02-08 17:50 -0800
Last post2013-02-11 08:57 +1100
Articles 20 on this page of 54 — 15 participants

Back to article view | Back to comp.lang.python


Contents

  LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-08 17:50 -0800
    Re: LangWart: Method congestion from mutate multiplicty Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-09 14:36 +1100
      Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-09 19:54 -0800
        Re: LangWart: Method congestion from mutate multiplicty Chris Angelico <rosuav@gmail.com> - 2013-02-10 15:20 +1100
        Re: LangWart: Method congestion from mutate multiplicty Mark Janssen <dreamingforward@gmail.com> - 2013-02-09 20:53 -0800
          Re: LangWart: Method congestion from mutate multiplicty Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-11 01:29 +1100
            Re: LangWart: Method congestion from mutate multiplicty Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2013-02-10 14:03 -0500
              Re: LangWart: Method congestion from mutate multiplicty Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-11 11:11 +1100
            Re: LangWart: Method congestion from mutate multiplicty Mark Janssen <dreamingforward@gmail.com> - 2013-02-10 13:28 -0800
              Re: LangWart: Method congestion from mutate multiplicty Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-11 11:10 +1100
                Re: LangWart: Method congestion from mutate multiplicty Mark Janssen <dreamingforward@gmail.com> - 2013-02-10 17:14 -0800
            Re: LangWart: Method congestion from mutate multiplicty Chris Angelico <rosuav@gmail.com> - 2013-02-11 08:51 +1100
            Re: LangWart: Method congestion from mutate multiplicty Mark Janssen <dreamingforward@gmail.com> - 2013-02-10 14:01 -0800
        Re: LangWart: Method congestion from mutate multiplicty Terry Reedy <tjreedy@udel.edu> - 2013-02-10 03:39 -0500
          Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-10 10:45 -0800
            Re: LangWart: Method congestion from mutate multiplicty Terry Reedy <tjreedy@udel.edu> - 2013-02-10 16:44 -0500
            Re: LangWart: Method congestion from mutate multiplicty Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-11 11:11 +1100
          Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-10 10:45 -0800
        Re: LangWart: Method congestion from mutate multiplicty Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-10 22:29 +1100
          Re: LangWart: Method congestion from mutate multiplicty Chris Angelico <rosuav@gmail.com> - 2013-02-11 00:24 +1100
            Re: LangWart: Method congestion from mutate multiplicty Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-11 01:00 +1100
          Re: LangWart: Method congestion from mutate multiplicty Tim Chase <python.list@tim.thechases.com> - 2013-02-10 07:52 -0600
          Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-10 15:59 -0800
            Re: LangWart: Method congestion from mutate multiplicty Tim Chase <python.list@tim.thechases.com> - 2013-02-10 18:12 -0600
              Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-10 17:24 -0800
              Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-10 17:24 -0800
            Re: LangWart: Method congestion from mutate multiplicty Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-11 11:36 +1100
              Re: LangWart: Method congestion from mutate multiplicty MRAB <python@mrabarnett.plus.com> - 2013-02-11 02:03 +0000
              Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-11 04:53 -0800
                Re: LangWart: Method congestion from mutate multiplicty Chris Angelico <rosuav@gmail.com> - 2013-02-12 00:27 +1100
                  Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-11 20:55 -0800
                    Re: LangWart: Method congestion from mutate multiplicty Mark Janssen <dreamingforward@gmail.com> - 2013-02-11 21:28 -0800
                      Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-12 12:46 -0800
                      Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-12 12:46 -0800
                  Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-11 20:55 -0800
            Re: LangWart: Method congestion from mutate multiplicty alex23 <wuwei23@gmail.com> - 2013-02-10 18:05 -0800
              Re: LangWart: Method congestion from mutate multiplicty Mark Lawrence <breamoreboy@yahoo.co.uk> - 2013-02-11 07:19 +0000
              Re: LangWart: Method congestion from mutate multiplicty Chris Angelico <rosuav@gmail.com> - 2013-02-11 18:24 +1100
              Re: LangWart: Method congestion from mutate multiplicty Mark Lawrence <breamoreboy@yahoo.co.uk> - 2013-02-11 07:35 +0000
              Re: LangWart: Method congestion from mutate multiplicty Tim Chase <tim@thechases.com> - 2013-02-11 06:04 -0600
              Re: LangWart: Method congestion from mutate multiplicty Serhiy Storchaka <storchaka@gmail.com> - 2013-02-11 19:07 +0200
        Re: LangWart: Method congestion from mutate multiplicty Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2013-02-10 13:30 +0000
          Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-10 16:25 -0800
            Re: LangWart: Method congestion from mutate multiplicty Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-11 11:42 +1100
          Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-10 16:25 -0800
        Re: LangWart: Method congestion from mutate multiplicty Mark Janssen <dreamingforward@gmail.com> - 2013-02-10 10:45 -0800
      Re: LangWart: Method congestion from mutate multiplicty 88888 Dihedral <dihedral88888@googlemail.com> - 2013-02-10 06:33 -0800
    Re: LangWart: Method congestion from mutate multiplicty Chris Angelico <rosuav@gmail.com> - 2013-02-09 15:51 +1100
      Re: LangWart: Method congestion from mutate multiplicty alex23 <wuwei23@gmail.com> - 2013-02-10 17:56 -0800
        Re: LangWart: Method congestion from mutate multiplicty Chris Angelico <rosuav@gmail.com> - 2013-02-12 19:06 +1100
    Re: LangWart: Method congestion from mutate multiplicty Neil Hodgson <nhodgson@iinet.net.au> - 2013-02-10 20:53 +1100
      Re: LangWart: Method congestion from mutate multiplicty Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-10 22:30 +1100
      Re: LangWart: Method congestion from mutate multiplicty Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-10 10:55 -0800
        Re: LangWart: Method congestion from mutate multiplicty Neil Hodgson <nhodgson@iinet.net.au> - 2013-02-11 08:57 +1100

Page 1 of 3  [1] 2 3  Next page →


#38490 — LangWart: Method congestion from mutate multiplicty

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-02-08 17:50 -0800
SubjectLangWart: Method congestion from mutate multiplicty
Message-ID<680e50a4-6569-49cf-b369-0be450545d50@googlegroups.com>
DISCLAIMER:
This post covers a universal programming language design flaw using both Python and Ruby code examples to showcase the issue. 

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.

However, learning a new language (be it by this method or by official docs) is frustrating when languages have method congestion from a need to present their users with both a method for "in-place-mutation" and method for "mutation-of-a-copy"; both sharing an almost exact spelling! 

Yes i know, naming conventions can help. And one widely used convention is to use weak verbs for the "mutation of a copy" and strong verbs for "in-place mutation", consider:

py> a.reverse -> mutate 'a'
py> a.reversed -> new Array

However you will sooner or later encounter a word that does not have a proper "weak verb" variant to describe the copy-mutate action, consider:

rb> point3d.offset(vector3d) -> mutate 'point3d'
rb> point3d.offseted(vector3d) -> HUH?

The Ruby language attempted to save the programmer from the scourge of obtaining a four year degree in linguistics just to create intuitive identifiers "on-the-fly", and they tried to remove this ambiguity by employing "post-fix-punctuation" of the exclamation mark as a visual cue for in-place modification of the object:

rb> a = [1,2,3]
rb> a.reverse!()
[3,2,1]
rb> a
[3,2,1]

...think of the exclamation mark yelling out; "Hey, i will modify this object so be careful dude!"  On the other hand, a method that mutates a copy will have the same identifier except /without/ the exclamation mark:

rb> a = [1,2,3]
rb> a.reverse()
[3,2,1]
rb> a
[1,2,3]

Now whilst this punctuation solves the ambiguity issue in a reasonable manner, it does not solve the congestion issue because for /every/ method that returns a copy of the object, another method will exist with an exclamation mark post-fixed that signifies object mutation. I don't like this because when i inspect the object i see redundant method names:

rb> mutators = a.methods.grep(/.*!/)
rb> copyers = a.methods.select{|x| mutators.include?(x+"!")}
rb> copyers+mutators.sort
rb> ["flatten", "transform", "collect", "sort", "map", "uniq", "offset", "reverse", "compact", "reject", "normalize", "slice", "collect!", "compact!", "flatten!", "map!", "normalize!", "offset!", "reject!", "reverse!", "slice!", "sort!", "transform!", "uniq!"]

Now that's just a small subset of the member functions of the Array object! Can you imagine the mental overload induced when the entire set of methods must be rummaged through each and every time!!! 

rb> a.methods.length
141

*look-of-disapproval*

============================================================
 SOLUTION
============================================================

The solution is simple. Do not offer the "copy-mutate" methods and force all mutation to happen in-place: 

py> l = [1,2,3]
py> l.reverse
py> l
[3,2,1]

If the user wants a "mutated copy" he should explicitly create a new object and then apply the correct mutator method:

py> a1 = [1,2,3]
py> a2 = list(a1).reverse()
py> a1
[1,2,3]
py> a2
[3,2,1]

[toc] | [next] | [standalone]


#38494

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-02-09 14:36 +1100
Message-ID<5115c455$0$6574$c3e8da3$5496439d@news.astraweb.com>
In reply to#38490
Rick Johnson wrote:

> The solution is simple. Do not offer the "copy-mutate" methods and force
> all mutation to happen in-place:
> 
> py> l = [1,2,3]
> py> l.reverse
> py> l
> [3,2,1]
> 
> If the user wants a "mutated copy" he should explicitly create a new
> object and then apply the correct mutator method:
> 
> py> a1 = [1,2,3]
> py> a2 = list(a1).reverse()


Oh wow, Rick has re-discovered programming in Python during the mid to late
1990s!

I was there, and I remember what it was like. For about a month, you try
hard to follow Rick's prescription. Then you realise that with a small
helper function, you can halve the amount of code it takes to do a common
operation:

def reversed(sequence):
    seq = list(sequence)
    seq.reverse()
    return seq


Soon you've copied this reversed() function into all your projects. And of
course, they start to diverge... in project A, you only care about lists.
In project B, you realise that you also need to support tuples and strings:


def reversed(sequence):
    seq = sequence[:]
    try:
        seq.reverse()
    except AttributeError:
        seq = seq[::-1]
    return seq

which in project C you realise can be shortened:

def reversed(sequence):
    return sequence[::-1]


until you get to project D when you realise that you also want this to work
on dicts:

def reversed(sequence):
    everything = list(sequence)
    return everything[::-1]


and then in project E you wonder why reversed(string) returns a list:

def reversed(sequence):
    everything = list(sequence)[::-1]
    if isinstance(sequence, tuple):
        return tuple(everything)
    elif isinstance(sequence, str):
        return ''.join(everything)
    return everything


and then finally you learn about iterators and generators and become more
comfortable with a flow-based programming paradigm and generators:

def reversed(sequence):
    for item in list(sequence)[::-1]:
        yield item

at which point you realise that, hell, this is so useful that pretty much
everyone has implemented it a dozen times or more in their own projects,
and you start to agitate for it to be added to the builtins so that there
is *one* implementation, done *right*, that everyone can use.

And then you get told that Guido's time machine has struck again, because
Python has already had this since Python 2.4.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#38548

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-02-09 19:54 -0800
Message-ID<d405822d-2252-4a85-8ab2-38ca88963d91@googlegroups.com>
In reply to#38494
On Friday, February 8, 2013 9:36:52 PM UTC-6, Steven D'Aprano wrote:
> Rick Johnson wrote:
> 
> > The solution is simple. Do not offer the "copy-mutate" methods and force
> > all mutation to happen in-place:
> > 
> > py> l = [1,2,3]
> > py> l.reverse
> > py> l
> > [3,2,1]
> > 
> > If the user wants a "mutated copy" he should explicitly create a new
> > object and then apply the correct mutator method:
> > 
> > py> a1 = [1,2,3]
> > py> a2 = list(a1).reverse()
> 
> Oh wow, Rick has re-discovered programming in Python during the mid to late
> 1990s!
> 
> [...snip: long-winded, rambling, and sarcastic response simply to convey 
> that Python lists have had a "reversed" method for some time...]

Steven, i am quite aware of the Python list method "reversed" --which returns a copy of the current list object in reversed order--, my point is that these types of "copy-mutate" methods superfluously pollute the object namespace. Do you really want "method pairs" like these:

 sort, sorted
 reverse, reversed

Hell, why stop there:

 append, appended
 flatten, flattened
 insert, inserted
 map, mapped
 filter, filtered
 reduce, reduced
 extend, extended
 freeze, frozen
 set, sat|setted
 unique, uniqued

Is this really what you prefer? Where does the madness end Steven? At what point do you say enough is enough? And what happens if you fail to catch the infection early enough? Steven, this is a /real/ problem which has the potential to go viral!

My point was this: All mutate methods should 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. 

 NO: reversed = lst.reversed() # Python
YES: reversed = list(lst).reverse() # Python

 NO: reversed = a.reverse() # Ruby
YES: reversed = Array.new(a).reverse!() # Ruby

This is about consistency and keeping the number of methods from spiraling out of control because we feel the need to automate /every/ task for the programmer, when in actuality, we are doing more harm than good.

[toc] | [prev] | [next] | [standalone]


#38549

FromChris Angelico <rosuav@gmail.com>
Date2013-02-10 15:20 +1100
Message-ID<mailman.1568.1360470027.2939.python-list@python.org>
In reply to#38548
On Sun, Feb 10, 2013 at 2:54 PM, Rick Johnson
<rantingrickjohnson@gmail.com> wrote:
> My point was this: All mutate methods should 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.

I agree. And we can go further and declare that there is only one data
type, the simple integer; you have an infinite number of them, and all
you can do is mutate them in place. You don't need variable names
either; just have one single array that represents your whole
namespace, and work with positions in that array. And don't bother
with actual positions, even - with a single pointer, you could manage
everything.

Forget this silly mess of data types, methods, global functions, and
so on. Let's simplify things massively!

Ook. Ook!

ChrisA

[toc] | [prev] | [next] | [standalone]


#38554

FromMark Janssen <dreamingforward@gmail.com>
Date2013-02-09 20:53 -0800
Message-ID<mailman.1571.1360472029.2939.python-list@python.org>
In reply to#38548
On Sat, Feb 9, 2013 at 8:20 PM, Chris Angelico <rosuav@gmail.com> wrote:
> On Sun, Feb 10, 2013 at 2:54 PM, Rick Johnson
> <rantingrickjohnson@gmail.com> wrote:
>> My point was this: All mutate methods should 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.
>
> I agree. And we can go further and declare that there is only one data
> [sarcasm]

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.  Guessing method names is far
suboptimal to this simple, easy idiom.  As for the point Chris was
making as to making all types one, I actually agree there too, it's
just that in order to do that, python would need a unified object
model and it doesn't have one yet.

Mark

[toc] | [prev] | [next] | [standalone]


#38572

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-02-11 01:29 +1100
Message-ID<5117aeca$0$29982$c3e8da3$5496439d@news.astraweb.com>
In reply to#38554
Mark Janssen wrote:

> On Sat, Feb 9, 2013 at 8:20 PM, Chris Angelico <rosuav@gmail.com> wrote:
>> On Sun, Feb 10, 2013 at 2:54 PM, Rick Johnson
>> <rantingrickjohnson@gmail.com> wrote:
>>> My point was this: All mutate methods should 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.
>>
>> I agree. And we can go further and declare that there is only one data
>> [sarcasm]
> 
> 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,

Perhaps so, but consider how you creates new objects in Python. Very rarely
do you do so with an explicit call to the constructor. For example:

n = 5  # Yes.
# or
n = int("5")  # No.

alist = some_list[1:]  # Yes.
# or
alist = list()
alist.extend(some_list[1:])  # No.

items = sorted(other_things + [1])  # Yes.
# or
items = other_things[:]
items.append(1)
items.sort()  # Hell no.


There are many functions or methods that create new objects, apart from the
constructor. A call like:

    blist = sorted(alist)

is no less explicitly creating a new list than:

    blist = list(alist)


> should be the Only One Way to Do It.

Pardon me, but you've been listening to too many Perl developers. "Only One
Way To Do It" is not, and never has been, the motto of Python. You may be
thinking of the line from the Zen of Python:

py> import this
[...]
There should be one-- and preferably only one --obvious way to do it.


The emphasis is on the *obvious*, not the "only". There is an enormous
difference between prohibiting a second way to solve problems ("Only One
Way") and recommending that there should be an Obvious Way.


> Guessing method names is far 
> suboptimal to this simple, easy idiom.  As for the point Chris was
> making as to making all types one, I actually agree there too,

Oh dear. Chris was being sarcastic. I thought that, even if the sarcasm
wasn't obvious, his "Ook. Ook!" at the end should have given it away:

http://www.dangermouse.net/esoteric/ook.html


> it's 
> just that in order to do that, python would need a unified object
> model and it doesn't have one yet.


I'm not sure what you mean by "unified object model", but I'm pretty sure
that Python has one. Everything is an object, with a single[1] hierarchy of
classes.



[1] Python 3 only. In Python 2, you have types, and you have old-style
classes, and they are separate.

-- 
Steven

[toc] | [prev] | [next] | [standalone]


#38598

FromDennis Lee Bieber <wlfraed@ix.netcom.com>
Date2013-02-10 14:03 -0500
Message-ID<mailman.1598.1360523024.2939.python-list@python.org>
In reply to#38572
On Mon, 11 Feb 2013 01:29:30 +1100, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> declaimed the following in
gmane.comp.python.general:

> 
> Oh dear. Chris was being sarcastic. I thought that, even if the sarcasm
> wasn't obvious, his "Ook. Ook!" at the end should have given it away:
> 
> http://www.dangermouse.net/esoteric/ook.html
>

	Ah... and here I thought it might have been a subtle reference to
the Librarian of the Unseen University...
http://en.wikipedia.org/wiki/Unseen_University#Librarian
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
        wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

[toc] | [prev] | [next] | [standalone]


#38618

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-02-11 11:11 +1100
Message-ID<51183715$0$29979$c3e8da3$5496439d@news.astraweb.com>
In reply to#38598
Dennis Lee Bieber wrote:

> On Mon, 11 Feb 2013 01:29:30 +1100, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> declaimed the following in
> gmane.comp.python.general:
> 
>> 
>> Oh dear. Chris was being sarcastic. I thought that, even if the sarcasm
>> wasn't obvious, his "Ook. Ook!" at the end should have given it away:
>> 
>> http://www.dangermouse.net/esoteric/ook.html
>>
> 
> Ah... and here I thought it might have been a subtle reference to
> the Librarian of the Unseen University...
> http://en.wikipedia.org/wiki/Unseen_University#Librarian

Not so subtle. The creator of Ook obviously is a fan.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#38602

FromMark Janssen <dreamingforward@gmail.com>
Date2013-02-10 13:28 -0800
Message-ID<mailman.1601.1360531742.2939.python-list@python.org>
In reply to#38572
On Sun, Feb 10, 2013 at 6:29 AM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> 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,
>
> Perhaps so, but consider how you creates new objects in Python. Very rarely
> do you do so with an explicit call to the constructor. For example:
>
> n = 5  # Yes.
> # or
> n = int("5")  # No.

Good, alright, this is the point where the concept of a unified object
model comes into play.  (Actually, I'm going to say "unified data
model" (or UDM) from now on so as to avoid the confusion that you
point out below that Python seems to already have a "unified object
model" because everything derives from "Object".  The point is
actually rather subtle.)

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.

(Note that everything in a computer is series of these "atomic" bits
organized by the machine into "words" (merely for sake of the
efficiency that such parallelization affords), yet we have these
human-language constructs such as lists and sets (or records, files,
arrays, etc) where *no such things exist in the computer*.   Hence,
the usefulness of considering a unified data model as part of the
computer *science*.)

In your example above, you can verify, for example, that the identity
of 5 and int("5") is the same -- even though you're using a
constructor syntax, you're not *constructing* anything at all, which
you may know already (somewhere in the Python docs, Guido points out
that Python pre-constructs the first 100 or so integers as I recall.)
There is, in addition, an implicit constructor for integers, such that
saying 656565 in python will actually construct the integer as if you
said "int("656565")".

In any case, one never operates or concerns oneself with copies of
atomic elements because they are all the same.  It's a subtle
meta-philosophical(?) point, not that different that that which occurs
in the science of physics regarding electrons and protons ("Is there
only one electron?":
http://en.wikipedia.org/wiki/One-electron_universe).

> py> import this
> [...]
> There should be one-- and preferably only one --obvious way to do it.

Yes, that is the reference.

>> Guessing method names is far
>> suboptimal to this simple, easy idiom.  As for the point Chris was
>> making as to making all types one, I actually agree there too,
>
> Oh dear. Chris was being sarcastic. I thought that, even if the sarcasm
> wasn't obvious, his "Ook. Ook!" at the end should have given it away:

Yes, I was aware of his sarcasm.  But I was actually wanting to agree
with the fundamental idea:  that one could reduce all data types to 1
atomic unit and 1 grouping construct, and like set theory in
mathematics, derive everything else.

>> it's
>> just that in order to do that, python would need a unified object
>> model and it doesn't have one yet.
>
> I'm not sure what you mean by "unified object model", but I'm pretty sure
> that Python has one. Everything is an object, with a single[1] hierarchy of
> classes.

Hopefully the elucidation above clears up some of that confusion.

Mark

[toc] | [prev] | [next] | [standalone]


#38617

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-02-11 11:10 +1100
Message-ID<511836f7$0$29979$c3e8da3$5496439d@news.astraweb.com>
In reply to#38602
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/articles/fog0000000018.html

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



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#38626

FromMark Janssen <dreamingforward@gmail.com>
Date2013-02-10 17:14 -0800
Message-ID<mailman.1613.1360545268.2939.python-list@python.org>
In reply to#38617
On Sun, Feb 10, 2013 at 4:10 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> 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/articles/fog0000000018.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

[toc] | [prev] | [next] | [standalone]


#38604

FromChris Angelico <rosuav@gmail.com>
Date2013-02-11 08:51 +1100
Message-ID<mailman.1603.1360533094.2939.python-list@python.org>
In reply to#38572
On Mon, Feb 11, 2013 at 8:28 AM, Mark Janssen <dreamingforward@gmail.com> wrote:
> Yes, I was aware of his sarcasm.  But I was actually wanting to agree
> with the fundamental idea:  that one could reduce all data types to 1
> atomic unit and 1 grouping construct, and like set theory in
> mathematics, derive everything else.

There are many things that work fine in theory, but aren't practical.
You could theoretically rewrite any Python program in Ook (or its
non-G-rated cousin), but that doesn't mean that Ook's data model is
worth working with. You could write a Python-to-Ook compiler, perhaps,
for what that's worth. Proving these things possible may be of
curiosity value, but I wouldn't want to actually _work with_ such a
system.

A while ago I put together a language concep[1]t that, similarly,
started with nothing and let the programmer build from there. It
quickly proved to have one massive fundamental flaw: that two
programs, ostensibly written in the same language, could be utterly
and completely different. It'd be like treating Python and bash
scripts as the same language, given that the shebang at the top makes
them both execute just fine. If you reduce everything to nothing, you
(1) force the programmer to do a lot of unnecessary work, and (2)
allow two different programmers to do that work subtly differently and
thus create incompatible programs. (Python already has a little of
this, in that Py2 and Py3 files aren't guaranteed compatible; but
imagine if every source file were different.)

[1] Posted here if you care. http://rosuav.com/1/?id=683

ChrisA

[toc] | [prev] | [next] | [standalone]


#38606

FromMark Janssen <dreamingforward@gmail.com>
Date2013-02-10 14:01 -0800
Message-ID<mailman.1604.1360533711.2939.python-list@python.org>
In reply to#38572
On Sun, Feb 10, 2013 at 1:51 PM, Chris Angelico <rosuav@gmail.com> wrote:
> On Mon, Feb 11, 2013 at 8:28 AM, Mark Janssen <dreamingforward@gmail.com> wrote:
>> Yes, I was aware of his sarcasm.  But I was actually wanting to agree
>> with the fundamental idea:  that one could reduce all data types to 1
>> atomic unit and 1 grouping construct, and like set theory in
>> mathematics, derive everything else.
>
> There are many things that work fine in theory, but aren't practical.
> You could theoretically rewrite any Python program in Ook (or its
> non-G-rated cousin), but that doesn't mean that Ook's data model is
> worth working with.

Ah, but you're conflating a *data model* (which is already composed of
simple theoretical elements (like 1/0)) and a *programming language*,
which is composed of either an implicit or explicit data model
(usually the former) AND a set of transforms that operate on it.
IOW, I'm wanting to take something that is usually just inherited and
historical (and thereby taken for granted), and make it something to
look at.  Traditional Data Structures in CompSci goes somewhat towards
this end, but doesn't quite take the idea to its ultimate, and that's
what I'm proposing with a unified data model.

mark

[toc] | [prev] | [next] | [standalone]


#38560

FromTerry Reedy <tjreedy@udel.edu>
Date2013-02-10 03:39 -0500
Message-ID<mailman.1577.1360485575.2939.python-list@python.org>
In reply to#38548
While it is true that sorted(iterable) is essentially

def sorted(iterable):
   tem = list(iterable)
   tem.sort
   return tem

the body is not an expression and cannot be substituted in an 
expression. The need for the short form was thought common enough to be 
worth, *on balance*, a new builtin name. It is not surprising that not 
all agree.

Reversed(iterable) is more complicated because it returns an iterator, 
not a list, and looks for a class-specific __reversed__ method. I think 
it is more or less equivalent to the following:

def _rev_iter(seq, n):
   for i in range(n-1, -1, -1):
   # many people have trouble getting the range right
     yield seq[i]

def reversed(iterable):
   try:
     return iterable.__reversed__()
   except AttributeError:
     try:
       itlen = iterable.__len__
       iterable.__getitem__
       return _rev_iter(iterable, itlen)
     except AttributeError:
       raise TypeError("argument to reversed() must be a sequence")

Even if list mutation methods returned the list, which they do not and 
for good reason, reversed(it) is not the same as list(it).reverse(). So 
that part of the premise of this thread is wrong.

-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#38595

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-02-10 10:45 -0800
Message-ID<14880592-debf-42de-8756-e47e59aeb302@googlegroups.com>
In reply to#38560
On Sunday, February 10, 2013 2:39:21 AM UTC-6, Terry Reedy wrote:
> While it is true that sorted(iterable) is essentially
> 
> def sorted(iterable):
>    tem = list(iterable)
>    tem.sort
>    return tem
> 
> the body is not an expression and cannot be substituted in an 
> expression. 

Yes but the body can be compressed to this single line: "list(iterable).sort()"

> Reversed(iterable) is more complicated because it returns an iterator, 
> not a list, and looks for a class-specific __reversed__ method. 
> [...]

Well if you're taking the position that iterators are difficult to create i say you are exaggerating a bit. Using the for loop:

py> for LOCALVAR in SEQUENCE:
...     do_something

we can get the iterator for free. If however you want to control the iteration /without/ being locked into a loop, you can explicitly call:

py> iter(seq)

Or, if you prefer methods over global functions: 

py> seq.__iter__()

Or, if python employed /true/ OOP paradigm:

py> Iterator(seq)

> Even if list mutation methods returned the list, which they do not and 
> for good reason, 

I am not proposing that in-place modification return the object.

> reversed(it) is not the same as list(it).reverse(). So 
> that part of the premise of this thread is wrong.

Well, it's not the same /now/, because of how Python handles this operation. The status quo is to encourage the implicit idiom over the explicit, however, this behavior could be optimized to cleanly handle /explicit/ syntax only. 

[toc] | [prev] | [next] | [standalone]


#38603

FromTerry Reedy <tjreedy@udel.edu>
Date2013-02-10 16:44 -0500
Message-ID<mailman.1602.1360532685.2939.python-list@python.org>
In reply to#38595
On 2/10/2013 1:45 PM, Rick Johnson wrote:
> On Sunday, February 10, 2013 2:39:21 AM UTC-6, Terry Reedy wrote:
>> While it is true that sorted(iterable) is essentially
>>
>> def sorted(iterable):
>>     tem = list(iterable)
>>     tem.sort
>>     return tem
>>
>> the body is not an expression and cannot be substituted in an
>> expression.
>
> Yes but the body can be compressed to this single line: "list(iterable).sort()"

That single line now evaluates to None, so that does not work.

>> Even if list mutation methods returned the list, which they do not and
>> for good reason,
>
> I am not proposing that in-place modification return the object.

It seems to me that you are, as that is the only way for 
'list(iterable).sort()' to replace 'sorted(iterable)', as you proposed 
both originally and above.

The reason sorted(iterable) was added is 'list(iterable).sort()', which 
newbies would try, *does not work*. Sorted was added so people would not 
have to write

tem = list(iterable)
tem.sort()
<statement using tem>
del tem

as they did previously, and instead could write

<statement using sorted(iterable)>

Reversed was added not only for the same reason, but also to avoid the 
temporary list altogether when not actually needed, which it often or 
usually is not.

-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#38619

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-02-11 11:11 +1100
Message-ID<51183726$0$29979$c3e8da3$5496439d@news.astraweb.com>
In reply to#38595
Rick Johnson wrote:

> we can get the iterator for free. If however you want to control the
> iteration /without/ being locked into a loop, you can explicitly call:
> 
> py> iter(seq)

> Or, if python employed /true/ OOP paradigm:
> 
> py> Iterator(seq)

Today I learned that the difference between "true" OOP and everything else
is the presence of an initial capital letter.

Thank you Rick for your deep insight.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#38597

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-02-10 10:45 -0800
Message-ID<mailman.1597.1360522696.2939.python-list@python.org>
In reply to#38560
On Sunday, February 10, 2013 2:39:21 AM UTC-6, Terry Reedy wrote:
> While it is true that sorted(iterable) is essentially
> 
> def sorted(iterable):
>    tem = list(iterable)
>    tem.sort
>    return tem
> 
> the body is not an expression and cannot be substituted in an 
> expression. 

Yes but the body can be compressed to this single line: "list(iterable).sort()"

> Reversed(iterable) is more complicated because it returns an iterator, 
> not a list, and looks for a class-specific __reversed__ method. 
> [...]

Well if you're taking the position that iterators are difficult to create i say you are exaggerating a bit. Using the for loop:

py> for LOCALVAR in SEQUENCE:
...     do_something

we can get the iterator for free. If however you want to control the iteration /without/ being locked into a loop, you can explicitly call:

py> iter(seq)

Or, if you prefer methods over global functions: 

py> seq.__iter__()

Or, if python employed /true/ OOP paradigm:

py> Iterator(seq)

> Even if list mutation methods returned the list, which they do not and 
> for good reason, 

I am not proposing that in-place modification return the object.

> reversed(it) is not the same as list(it).reverse(). So 
> that part of the premise of this thread is wrong.

Well, it's not the same /now/, because of how Python handles this operation. The status quo is to encourage the implicit idiom over the explicit, however, this behavior could be optimized to cleanly handle /explicit/ syntax only. 

[toc] | [prev] | [next] | [standalone]


#38563

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-02-10 22:29 +1100
Message-ID<511784b3$0$29988$c3e8da3$5496439d@news.astraweb.com>
In reply to#38548
Rick Johnson wrote:

> On Friday, February 8, 2013 9:36:52 PM UTC-6, Steven D'Aprano wrote:
>> Rick Johnson wrote:
>> 
>> > The solution is simple. Do not offer the "copy-mutate" methods and
>> > force all mutation to happen in-place:
>> > 
>> > py> l = [1,2,3]
>> > py> l.reverse
>> > py> l
>> > [3,2,1]
>> > 
>> > If the user wants a "mutated copy" he should explicitly create a new
>> > object and then apply the correct mutator method:
>> > 
>> > py> a1 = [1,2,3]
>> > py> a2 = list(a1).reverse()
>> 
>> Oh wow, Rick has re-discovered programming in Python during the mid to
>> late 1990s!
>> 
>> [...snip: long-winded, rambling, and sarcastic response simply to convey
>> that Python lists have had a "reversed" method for some time...]
> 
> Steven, i am quite aware of the Python list method "reversed" --which
> returns a copy of the current list object in reversed order--, 

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. People who actually programmed using Python before
reversed() and sorted() were added missed them, and consequently kept
reimplementing them.

You want to go back to the Bad Old Days when everyone was reimplementing the
same few functions over and over again. I say, boo sucks to that.


> my point is 
> that these types of "copy-mutate" methods superfluously pollute the object
> namespace. Do you really want "method pairs" like these:
> 
>  sort, sorted
>  reverse, reversed

Yes.


> Hell, why stop there:
> 
>  append, appended

"appended" is called list addition.

newlist = oldlist + [item_to_append]


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

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


>  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:]


>  map, mapped
>  filter, filtered
>  reduce, reduced

Those are nonsense. None of those are in-place mutator methods. Especially
reduce, which reduces a list to a single item. You might as well have
suggested "len, "lened".


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


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


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



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#38567

FromChris Angelico <rosuav@gmail.com>
Date2013-02-11 00:24 +1100
Message-ID<mailman.1578.1360502686.2939.python-list@python.org>
In reply to#38563
On Sun, Feb 10, 2013 at 10:29 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> "inserted" is called addition, together with list slicing when needed.
>
> newlist = [item_to_insert] + oldlist
> newlist = oldlist[0:5] + [item_to_insert] + oldlist[5:]

Really? Wouldn't it be easier to use slice assignment on a copy?

newlist = oldlist[:]; newlist[pos:pos] = [item_to_insert]

Actually, come to think of it, that scores about the same on
readability. Six of one, half dozen of the other.

ChrisA

[toc] | [prev] | [next] | [standalone]


Page 1 of 3  [1] 2 3  Next page →

Back to top | Article view | comp.lang.python


csiph-web