prototypes in Python [was: what is good in Prothon]

M

Michele Simionato

So far, I have not installed Prothon, nor I have experience with Io, Self
or other prototype-based languages. Still, from the discussion on the
mailing list, I have got the strong impression that you do not actually
need to fork Python in order to implement prototypes. It seems to me
that Python metaclasses + descriptors are more than powerful enough to
implementing prototypes in pure Python.

I wrote a module that implements part of what David MacQuigg discussed in
http://apache.ece.arizona.edu/~edatools/Python/Prototypes.htm in few lines
of code (disclaimer: this is an horrible hack that changes Python semantics
and makes "super" and "self" kinda of implicit reserved
keywords, highly unpythonic). It requires Python 2.2+.
I have not read the whole David MacQuigg's document, nor I have done any
serious testing of the module, nor I claim I do understand what prototypes
are; also I guarantee there will be bugs and surprising behaviors, but
still I think they could be fixed if I was willing to spend more time
on the issue.

Here is an example of usage:

from prototype import Prototype # prototypes are implemented as classes

class Animal(Prototype):
numAnimals = 0
home = "Earth"
def __init__(): # no need to pass self around
Animal.numAnimals += 1
def show():
print "Animals:", self.numAnimals

class Feline(Animal):
genus="Feline"
def __init__(name,sound): # no need to pass self around
super.__init__()
self.name=name
self.sound=sound
def talk(): # no need to pass self around
print "%s talking: %s!" % (self.genus,self.sound)

class Cat(Feline): # how to call the super prototype
numCats = 0
def __init__ ( n = "unknown", s = "Meow" ):
super.__init__(n,s)
Cat.numCats += 1
def show():
super.show()
print " Cats:", self.numCats
def talk():
print "My name is", self.name
print "I am a %s from %s" % (self.genus, self.home)
super.talk()

cat1 = Cat() # abuse of notation: makes a new prototype, not an instance

print cat1 # =>
# <class '__main__.Prototype:Cat'>

cat2 = Cat("Garfield")
cat2.home = "Tucson"

print cat2 # =>
# <class '__main__.Prototype:Cat'>

cat1.talk() # =>
# My name is unknown
# I am a Feline from Earth
# Feline talking: Meow!

cat2.talk()# =>
# My name is Garfield
# I am a Feline from Tucson
# Feline talking: Meow!

cat2.show() # =>
# Animals: 2
# Cats: 2

I am not sure this does what prototype people wants, but still it is
a nice example of how to abuse Python ;) Originally, I tried to use
"_" for "self" and "__" for "super", but with my fonts it was
difficult to distinguish between them. With a preprocessor one
could replace .name -> self.name and ..name -> super.name, but
I did no bother to do that.

Here is the module (not at all optimized):

$ cat prototype.py
import sys
from types import FunctionType
from inspect import isfunction

class methodwrapper(object): # descriptor
def __init__(self,func,cls):
self.__func__=func
self.__cls__=cls
def __get__(self,none,cls):
globs=sys.modules[cls.__module__].__dict__.copy()
globs["self"]=cls
globs["super"]=super(self.__cls__,cls)
return FunctionType(
self.__func__.func_code,
globs,
self.__func__.func_name,
self.__func__.func_defaults,
self.__func__.func_closure)

class _Prototype(type): # metaclass
def __init__(cls,name,bases,dic):
for k,v in dic.iteritems():
if isfunction(v):
setattr(cls,k,methodwrapper(v,cls))
super(_Prototype,cls).__init__(name,bases,dic)
def __call__(cls,*args,**kw):
newcls = type("Prototype:%s" % cls.__name__,(cls,),
{"__module__": cls.__module__})
newcls.__init__(*args,**kw)
return newcls

class Prototype(object): # mother of all prototypes
__metaclass__=_Prototype
def __init__(*args,**kw):
pass

#### END ####

Michele Simionato
 
H

has

So far, I have not installed Prothon, nor I have experience with Io, Self
or other prototype-based languages. Still, from the discussion on the
mailing list, I have got the strong impression that you do not actually
need to fork Python in order to implement prototypes. It seems to me
that Python metaclasses + descriptors are more than powerful enough to
implementing prototypes in pure Python.

"Metaclasses" and "prototypes"... <ouch> Now there's two words that
should NEVER appear in the same sentence (or even on the same planet,
for that matter). Metaclasses may be Manna for complexity junkies, but
they're nothing but a viciously bad joke imposed by those who ought to
have known better and perpetuated by those who never will.

One of the great advantages of proto-OO is it shows up metaclasses for
the ludicrous code masturbation they are. As to why they're still
here, lingering like the stench of long-dead rat from under the floor
when they should've been shitcanned years ago... well, draw your own
conclusions. (Two words of my own: "politics" and "religion".)

[BTW, this is a totally generic rant; please don't think it was meant
personally! It's just that, well... if there's two words guaranteed to
push ALL my wrong buttons, those two are it.<g> Anyway, <Rant Off> -
and let's get back to our scheduled program...]

--

As far as doing proto-OOP in Python is concerned, you can, but it'd be
a bit like doing OOP [of any flavour] in C. i.e. Not much fun. You
basically have to roll your own structures and runtime support, and
provide syntactic sugar via some kind of pre-processor or compiler
extension if you want it to be halfway decent for users to code in.

Here's a very simple, incomplete and very naive example to give you an
idea of how you might start attacking it:

#############################

class _DelegateStub:
"""Terminates the delegate chain."""

delegate = None
copy = staticmethod(lambda:_DelegateStub)


class Object:
"""This class defines the generic proto-OO object 'type' used to
create all objects."""

delegate = None # kludge
_dict = None # kludge

def __init__(self):
self.delegate = _DelegateStub
self._dict = {}

def __getattr__(self, name):
if self._dict.has_key(name):
return self._dict[name]
else:
return getattr(self.delegate, name)

def __setattr__(self, name, value):
if name in ['delegate', '_dict']:
self.__dict__[name] = value
else:
self._dict[name] = value

def copy(self):
"""Clone this object."""
new = Object()
new.delegate = self.delegate.copy()
new._dict = self._dict.copy()
return new


# Creating a new object from scratch:

# Define object 'foo'
foo = Object()
foo.a = 3
foo.b = 3
foo.multiply = lambda target:target.a*target.b


# Do stuff with object (note: due to lack of runtime magic, user
# must pass the target object to an object's 'method' themselves):

print foo.a, foo.b # --> 3 3
print foo.multiply(foo) # --> 9


# Creating a new object by cloning an existing one:

# Create object 'bar' by duplicating object 'foo'
bar = foo.copy()

print bar.multiply(bar) # --> 9

# Object 'bar' can be modified at will:

bar.a = -5
bar.c = 'hello world'

print bar.c # --> 'hello world'

print foo.multiply(foo) # --> 9
print bar.multiply(bar) # --> -15


# Behavioural composition through delegation:

# Create object 'zib' containing method 'power' with 'bar' as its
delegate
zib = Object()
zib.power = lambda target:target.a**target.b
zib.delegate = bar

print zib.c # --> 'hello world'
print zib.power(zib) # --> -125

#############################

Obviously, implementing a complete proto-OO system in and atop
Python's native class-OO system is going to be both tedious to use
(due to lack of syntactic sugar) and slow to execute (as it's all
interpreted Python code). Which is why it makes sense to start from
scratch as Mark is doing, or at least fork an existing language and
seriously strip down and rebuild it (which is a thought that's
previously crossed my own mind, though I lack the time, patience and C
skills to tacke such a project myself).
 
D

David MacQuigg

So far, I have not installed Prothon, nor I have experience with Io, Self
or other prototype-based languages. Still, from the discussion on the
mailing list, I have got the strong impression that you do not actually
need to fork Python in order to implement prototypes. It seems to me
that Python metaclasses + descriptors are more than powerful enough to
implementing prototypes in pure Python.

I wrote a module that implements part of what David MacQuigg discussed in
http://apache.ece.arizona.edu/~edatools/Python/Prototypes.htm in few lines
of code (disclaimer: this is an horrible hack that changes Python semantics
and makes "super" and "self" kinda of implicit reserved
keywords, highly unpythonic). It requires Python 2.2+.
I have not read the whole David MacQuigg's document, nor I have done any
serious testing of the module, nor I claim I do understand what prototypes
are; also I guarantee there will be bugs and surprising behaviors, but
still I think they could be fixed if I was willing to spend more time
on the issue.

This is amazing! I don't understand how it works, but it does provide
what I think the "classless" advocates are looking for, an ability to
"clone" one object from another, and avoid any "two-tier" organization
of instances and classes.
My name is Fluffy
I am a Feline from Earth
Feline talking: Purr!

It is a shame that the discussion has degenerated to the point where
most people are ignoring threads relating to prototypes. I have tried
repeatedly to get a simple requirements statement or use case, and get
nothing but sarcastic remarks. I have no experience with prototype
languages either, except a little with Prothon. I started to read a
paper, but fell asleep after a discussion on the "theory of
knowledge".

In spite of all this, there are some nuggets along the way. The
unification of methods and functions is the one I am most interested
in. The code below seems to have the machinery to do that, with the
elimination of 'self' from the argument list. That alllows static
methods to have exactly the same form as normal methods. ( The 'show'
methods below are actually static methods if you remove any references
to 'self', and replace them with explicit references, i.e.
self.numAnimals --> Animal.numAnimals ).

I agree with you that Python has the capability to implement
prototypes. Perhaps we can do that using metaclasses for some initial
experiments. Then if we get some constructive feedback, we can put
together a PEP to make prototypes part of the core language, add
better syntax, and fix whatever might not work quite right using
metaclasses.

I'm collecting ideas for Python 3 and 4 and putting them on my webpage
at http://ece.arizona.edu/~edatools/Python Python 3 includes features
that are not compatible with Python 2, but I believe are consistent to
the extent that Python 2 programs can be automatically translated to
Python 3. Python 4 has no such contraint. All that matters is that
the language is simple and elegant, and does useful things, as opposed
to things that are theoretically interesting. Your comments and
suggestions are welcome.

-- Dave
Here is an example of usage:

from prototype import Prototype # prototypes are implemented as classes

class Animal(Prototype):
numAnimals = 0
home = "Earth"
def __init__(): # no need to pass self around
Animal.numAnimals += 1
def show():
print "Animals:", self.numAnimals

class Feline(Animal):
genus="Feline"
def __init__(name,sound): # no need to pass self around
super.__init__()
self.name=name
self.sound=sound
def talk(): # no need to pass self around
print "%s talking: %s!" % (self.genus,self.sound)

class Cat(Feline): # how to call the super prototype
numCats = 0
def __init__ ( n = "unknown", s = "Meow" ):
super.__init__(n,s)
Cat.numCats += 1
def show():
super.show()
print " Cats:", self.numCats
def talk():
print "My name is", self.name
print "I am a %s from %s" % (self.genus, self.home)
super.talk()

cat1 = Cat() # abuse of notation: makes a new prototype, not an instance

print cat1 # =>
# <class '__main__.Prototype:Cat'>

cat2 = Cat("Garfield")
cat2.home = "Tucson"

print cat2 # =>
# <class '__main__.Prototype:Cat'>

cat1.talk() # =>
# My name is unknown
# I am a Feline from Earth
# Feline talking: Meow!

cat2.talk()# =>
# My name is Garfield
# I am a Feline from Tucson
# Feline talking: Meow!

cat2.show() # =>
# Animals: 2
# Cats: 2

I am not sure this does what prototype people wants, but still it is
a nice example of how to abuse Python ;) Originally, I tried to use
"_" for "self" and "__" for "super", but with my fonts it was
difficult to distinguish between them. With a preprocessor one
could replace .name -> self.name and ..name -> super.name, but
I did no bother to do that.

Here is the module (not at all optimized):

$ cat prototype.py
import sys
from types import FunctionType
from inspect import isfunction

class methodwrapper(object): # descriptor
def __init__(self,func,cls):
self.__func__=func
self.__cls__=cls
def __get__(self,none,cls):
globs=sys.modules[cls.__module__].__dict__.copy()
globs["self"]=cls
globs["super"]=super(self.__cls__,cls)
return FunctionType(
self.__func__.func_code,
globs,
self.__func__.func_name,
self.__func__.func_defaults,
self.__func__.func_closure)

class _Prototype(type): # metaclass
def __init__(cls,name,bases,dic):
for k,v in dic.iteritems():
if isfunction(v):
setattr(cls,k,methodwrapper(v,cls))
super(_Prototype,cls).__init__(name,bases,dic)
def __call__(cls,*args,**kw):
newcls = type("Prototype:%s" % cls.__name__,(cls,),
{"__module__": cls.__module__})
newcls.__init__(*args,**kw)
return newcls

class Prototype(object): # mother of all prototypes
__metaclass__=_Prototype
def __init__(*args,**kw):
pass

#### END ####

Michele Simionato
 
M

Michele Simionato

David MacQuigg said:
The unification of methods and functions is the one I am most interested
in. The code below seems to have the machinery to do that, with the
elimination of 'self' from the argument list. That alllows static
methods to have exactly the same form as normal methods. ( The 'show'
methods below are actually static methods if you remove any references
to 'self', and replace them with explicit references, i.e.
self.numAnimals --> Animal.numAnimals ).

Probably you do not realize that methods and functions are *already*
unified in Python: they are both examples of descriptors. Descriptors
are maybe the most important thing in Python 2.2+, since the whole new style
object system is based on them. Not only: you can use descriptors to
implement an object system of your choice, as I did in the prototype
module; metaclasses just provide convenient syntactic sugar.

BTW, descriptors are very well discussed here:
http://users.rcn.com/python/download/Descriptor.htm
I agree with you that Python has the capability to implement
prototypes. Perhaps we can do that using metaclasses for some initial
experiments. Then if we get some constructive feedback, we can put
together a PEP to make prototypes part of the core language, add
better syntax, and fix whatever might not work quite right using
metaclasses.

Actually, I do NOT support the idea of making prototypes part of the
core language. If somebody wants to write and mantain a prototype module
that's fine, but I would be opposed to have it in the standard library.
There should be only one obvious object system in Python, and that
object system is not a prototype based one ;)
OTOH, there is nothing wrong about having a prototype module for people
wanting to experiment with prototypes without being forced to
abandon Python and its libraries.
I'm collecting ideas for Python 3 and 4 and putting them on my webpage
at http://ece.arizona.edu/~edatools/Python Python 3 includes features
that are not compatible with Python 2, but I believe are consistent to
the extent that Python 2 programs can be automatically translated to
Python 3. Python 4 has no such contraint. All that matters is that
the language is simple and elegant, and does useful things, as opposed
to things that are theoretically interesting. Your comments and
suggestions are welcome.

-- Dave

If I was writing a new language, I would do Python with prefix notation ;)

Seriously, I think that everybody interested in language design should
first study the existing languages and see what has already been
tried in the last fifty years: then probably 99% of "new" proposal
would be dismissed. I have not studied prototypes, so I may be wrong,
but I have a gut feeling that they are not such a good idea.

One thing I like about classes is that they are self-documenting: when you
see a class, you know which methods are in it. Of course, you can add
methods at run-time, but this is not good style: it is good to have the
ability, but you should not abuse it. OTOH, in prototype languages you
dynamically add methods all the time and the definitions are scattared in
different places, so it is not obvious to know what an object is doing
unless you read all the program (including imported modules).
This is already a problem with regular inheritance, prototype inheritance
would worsen the situation, at least ISTM and IMHO.


Michele Simionato
 
J

Jonathan Gardner

# Define object 'foo'
foo = Object()
foo.a = 3
foo.b = 3
foo.multiply = lambda target:target.a*target.b

I think this is the syntactic sugar that is missing: anonymous
functions come in one breed only: lambdas. This example fits neatly
into a lambda function, but more complicated examples won't.

For instance, you can't write:

def foo.multiply(self):
return self.a * self.b

I would imagine an easy way to do this would be to have this be
acceptable:

foo.multiple = def(self):
returns self.a * self.b

This will create an anonymous function and store it in foo.multiple.

I'll admit that classless OO programming looks neat. The only thing
that I can't see an obvious way of doing is to share a value or method
across multiple objects. For instance:

class A:
number = 0
def __init__(self):
number += 1
def __del__(self):
number -= 1

How would you share "number" across a similar class of objects?

Also, it kind of renders the question, "What kind of object is this?"
meaningless. There are no /kinds/ anymore, at least not built into the
language. You can go ahead and create objects that are classes, and
then make objects that have an attribute called "class", I guess.

I do enjoy seeing different perspectives from other communities. It
helps me get a new perspective with my own programming.
 
H

has

Actually, I do NOT support the idea of making prototypes part of the
core language.

Ditto. [To paraphrase:] There should be one, and preferably only one,
way of doing things. Including OOP.

If I was writing a new language, I would do Python with prefix notation ;)

You sick disturbed Lisp lover, you... ;p

Seriously, I think that everybody interested in language design should
first study the existing languages and see what has already been
tried in the last fifty years: then probably 99% of "new" proposal
would be dismissed.

Amen. (I figure in another ten or fifteen years somebody will finally
get round to successfully re-inventing Lisp as the Next Big Thing, and
then things can actually start moving forward again...)

I have not studied prototypes, so I may be wrong,
but I have a gut feeling that they are not such a good idea.

I have a gut feeling you should study them first, before asking your
gut for its opinion. A gut's gotta have something solid to chew on. ;)

One thing I like about classes is that they are self-documenting: when you
see a class, you know which methods are in it.

<cough>Dylan</cough>

(And Dylan is one of those languages that makes me tear up at the
thought of it. Perhaps someday its prince will come? One can but
hope...)

Of course, you can add
methods at run-time, but this is not good style: it is good to have the
ability, but you should not abuse it. OTOH, in prototype languages you
dynamically add methods all the time and the definitions are scattared in
different places, so it is not obvious to know what an object is doing
unless you read all the program (including imported modules).

I would say proto-OO philosophy is a bit closer to Lisp philosophy
than Java philosophy. However, I think you'll find good proto-OO
programmers have no more problems staying disciplined than good
class-based programmers.

Now, whether mediocre programmers would manage to screw up any worse
in proto-OO than class-OO is a separate question; but then, spaghetti
is spaghetti whatever the language. Sure you can spread object
behaviour from one end of the source to the other if you want to, but
you can also write 1000-line procedures in C - and it's not like you
can blame C's object model for that because it doesn't even have one.


So perhaps the solution isn't creating a more restrictive, less
flexible language (and then retroactively slapping all sorts of mad
complexity on top to cater for the competent users who quickly object
to the limitations it indiscriminately imposes upon them); but
creating a simple, open language that can scale extremely well as-is,
and providing training wheels to the more thoughtless, naive users
till they learn some responsibility for themselves.

Of course, that leaves you with the political problem that no l33t
hAx0r would ever admit to needing training wheels and will insist on
taking the biggest baddest Ferrari regardless of whether they're
competent to handle it or not. But then, it's not my responsibility to
keep them from wrapping their dumb selves round the first lamppost
they meet if that's what they'll insist on doing. Plus it's one less
doofus to be getting in my road later.;)

This is already a problem with regular inheritance, prototype inheritance
would worsen the situation, at least ISTM and IMHO.

Feel free to check out any of my proto-OO programming efforts, and
critique away. <g>

You might also check out my HTMLTemplate Python module, which although
it uses MI for behavioural composition retains many other aspects of
its original proto-OO design and philosophy. In a field dominated by
vast, lumbering PHP-copycats and wannabes, I think it rather makes for
one of those "breaths of fresh air" somebody mentioned earlier. ;)
 
H

has

I'll admit that classless OO programming looks neat. The only thing
that I can't see an obvious way of doing is to share a value or method
across multiple objects.

A couple of ways I can think of:

1. Store the value in a module-level variable. This is not so odd an
idea as it seems; e.g. see Dylan as one example of a [class-based] OO
language where encapsulation primarily happens at module rather than
class level. My own proto-OO code is generous in its use of modules
and procedures. BTW, this may work particularly well in a language
that has first-class syntactic support for declaring objects, as
that'll allow you to put multiple modules within a single file (and
modules within those modules, and so on, if that's what you want).

2. Create a single shared object to store this value, and pop a
reference to it into a slot in every object that uses it so they can
access it there. If you also want this value available to the objects'
clients as well as the objects themselves, you can always make that
slot into a parent slot so that external requests for the value are
automatically delegated to it.

Also, it kind of renders the question, "What kind of object is this?"
meaningless. There are no /kinds/ anymore, at least not built into the
language.

Yep. In its purest form, a proto-OO language would have only a single
'type' - object - and no 'classes' at all. While folk who are used to
relying on type/class information to make their programs work may
freak a bit at the thought of this, languages like Python and Ruby
have already demonstrated that 'duck typing' can work well. (Again,
it's mostly just a matter of the developer having a bit of discipline
in the first place than relying on the compiler to pick up their slop
after the event. I actually regard this particular justification for
static typing - "it helps reduce bugs" - as a physical abuse of the
type system. Anyway, if I ever feel the need for strong compile-time
typing I'll go learn OCaml or something else with a really smart,
sophisticated type system, not C/C++/Java. Or Dylan, which'll give me
best of both worlds.)

I do enjoy seeing different perspectives from other communities. It
helps me get a new perspective with my own programming.

Absolutely! Personally I'm only fluent in two languages - AppleScript
(my alma mater) and Python (my current development platform of choice)
- but I've tinkered with a few others (a little C, Perl, JavaScript,
for example), and read up on at least a dozen more (Lisp, Forth, Java,
Smalltalk, Eiffel, ML/OCaml, Ruby, Dylan, HyperCard, Obj-C to pop some
names off the top of my head; and various niche languages I can't even
remember the names of). Often I just get a vague impression of what
these languages are trying to do, particularly on my first attempt to
understand them, but after a while the pieces start to slot into place
and I'll maybe go read some more. Sure I'm a shallow dilletante who
clearly hasn't got enough Real Work to go do with themselves, but just
wait till I REALLY get started! (Which is sure to be any day now, oh
yes; any day...;)
 
H

has

David MacQuigg said:
This is amazing! I don't understand how it works, but it does provide
what I think the "classless" advocates are looking for, an ability to
"clone" one object from another, and avoid any "two-tier" organization
of instances and classes.

I posted an incomplete implementation of a simple proto-OO model built
It is a shame that the discussion has degenerated to the point where
most people are ignoring threads relating to prototypes.

Well, it has little direct bearing on Python discussions so most folk
probably aren't interested anyway.
I have tried
repeatedly to get a simple requirements statement or use case, and get
nothing but sarcastic remarks. I have no experience with prototype
languages either,

That would probably be your problem then. I think you need to knuckle
down and do some self-motivated research before trying to wade in at
the deep end. I mean, if a forty-watter like me can manage to digest
it, a smart person like yourself shouldn't have any trouble [as long
as you go into it with a completely open mind].
except a little with Prothon.

Pick a language that's a bit more established and mature (and isn't
currently right in the middle of a great philosophical war;).
I started to read a paper, but fell asleep after a discussion on the "theory of
knowledge".

Well, you still got further than me. Reading/writing papers is
definitely _not_ one of my strong points; I'm much more the hands-on
"give it a go and see what happens" type. I'm not averse to lightly
skimming the odd bit of high-falutin' academic papery, however, and
even when I really don't understand what it's about at least I come
away with the vague notion that there are Other Ideas that exist out
there, rather than hiding in my own self-imposed box pretending that's
really all there is. Better to serve [fries] in heaven than rule in
[cobol] hell, I say.

In spite of all this, there are some nuggets along the way. The
unification of methods and functions is the one I am most interested
in.

This is not a proto-OO issue.

BTW, if you want to see _really_ interesting things done with methods
and functions, go check out, say, Dylan. Multimethods are one of those
things that can sound really complex and intimidating at first
encounter - especially if you're only ever thought of OOP in terms of
how Java, Python, etc. do it - but are actually _incredibly_simple_,
not to mention rather beautiful. Go grok 'em; it'll really broaden
your mind.

I agree with you that Python has the capability to implement
prototypes. Perhaps we can do that using metaclasses for some initial
experiments. Then if we get some constructive feedback, we can put
together a PEP to make prototypes part of the core language, add
better syntax, and fix whatever might not work quite right using
metaclasses.

Wrong strategy. You cannot simplify an already complex thing by adding
even more stuff to it. I for one am already absolutely convinced that
proto-OO is ultimately the right way forward for the future of OOP on
dynamic languages, and that all the stuff we see and hear about Next
Big Things in [traditional] OOP, such as metaclasses and aspects, is
all just an almighty cloud of smoke generated by faddish, under-read
folk who have failed/refused to see/acknowledge that the problems they
are currently trying to solve now were/are A. already solved years
ago, but ignored then as now because they didn't fit neatly with the
then/current orthodoxy and would require significant backtracking to
adopt; and B. mostly generated by the various Really Bright Ideas To
Solve Our Problems they cooked up the last time round.

Of course, the longer that invested parties refuse to acknowledge the
fundamental flaws and mis-features in the foundation of their great
and grandiose sand castles in the sky and persist in pretending that
the solution is slopping even more flaws and mis-features on top, the
worse it's going to be for everybody when the whole lot _finally_
collapses under its own weight. So when that day comes, expect to see
me standing well to the side laughing my ass off.;)

has
 
D

David MacQuigg

Probably you do not realize that methods and functions are *already*
unified in Python: they are both examples of descriptors. Descriptors
are maybe the most important thing in Python 2.2+, since the whole new style
object system is based on them. Not only: you can use descriptors to
implement an object system of your choice, as I did in the prototype
module; metaclasses just provide convenient syntactic sugar.

Interesting! I wish that unification at the primitive level had been
provided in the original design of Python. Seems like the multiple
method styles we have now are just an historical accident.
BTW, descriptors are very well discussed here:
http://users.rcn.com/python/download/Descriptor.htm

Good article, but beyond my current capabilities and available time.
I'll keep this on my reference list.
Actually, I do NOT support the idea of making prototypes part of the
core language. If somebody wants to write and mantain a prototype module
that's fine, but I would be opposed to have it in the standard library.
There should be only one obvious object system in Python, and that
object system is not a prototype based one ;)
OTOH, there is nothing wrong about having a prototype module for people
wanting to experiment with prototypes without being forced to
abandon Python and its libraries.

I'm coming to the same conclusion, especially now I see that
prototypes can be done so easily in Python. If there is serious
interest in prototypes, someone will make the effort to finish your
module and commit to maintaining it. So far, I've seen too few
reasonable people favoring prototypes, and too many thoreticians,
egotistical fools, and anonymous trolls. :>)
If I was writing a new language, I would do Python with prefix notation ;)

Seriously, I think that everybody interested in language design should
first study the existing languages and see what has already been
tried in the last fifty years: then probably 99% of "new" proposal
would be dismissed. I have not studied prototypes, so I may be wrong,
but I have a gut feeling that they are not such a good idea.

So many languages. So little time. :>) Actually, I have found my
study of Ruby and Prothon to be helpful in learning Python better, and
it re-inforced my opinion that Python is the best choice for my own
project -- a circuit-design platform that I hope will be useful for
many years. Key factors in this choice are the excellent libraries,
third-party software, books, and large community that have been built
over the last ten years. The flaws in Python syntax are really minor
compared to all this.

Still, I wish there was something I could do about the flaws. From my
study of Ruby, I know that Python's string methods could be improved.
From Prothon, I know that all forms of functions and methods could be
unified in one simple form. It doesn't look like there is much
interest in these problems in the Python community, however, so I
think it is time to get back to my real job.
One thing I like about classes is that they are self-documenting: when you
see a class, you know which methods are in it. Of course, you can add
methods at run-time, but this is not good style: it is good to have the
ability, but you should not abuse it. OTOH, in prototype languages you
dynamically add methods all the time and the definitions are scattared in
different places, so it is not obvious to know what an object is doing
unless you read all the program (including imported modules).
This is already a problem with regular inheritance, prototype inheritance
would worsen the situation, at least ISTM and IMHO.

I couldn't have said it better. With an interactive interpreter and a
good editor, it is real easy to change any class or module. When I
want to make such a change, I don't rely on my memory to make changes
"on-the-fly". I find that class and spend a few minutes looking at it
to make sure my changes don't have unintended consequences. Then I
spend even longer re-running old tests to make sure I haven't broken
something totally unexpected. The new IDLE editor is nice, because I
can just hit F5 after every edit, and it re-initializes everything.

This is not to say that "on-the-fly" programming is wrong. It just
doesn't fit my need, which is a well-organized hierarchical system of
classes and instances, one that I can maintain, and expect others to
work on. I just can't imagine writing something like this by sticking
in last-minute "with" blocks containing numerous variables I forgot to
put in the original class definition.

-- Dave
 
G

Greg Ewing

David said:
On 1 May 2004 22:34:27 -0700, (e-mail address removed) (Michele
Simionato) wrote:
>
>
Interesting! I wish that unification at the primitive level had been
provided in the original design of Python.

It was. Methods have always been no more than functions that
happen to live in classes, and they still are. Descriptors are
a red herring here; they're just a generalisation that allows for
some new things. They don't unify anything that was previously
existing but not unified.
 
D

David MacQuigg

It was. Methods have always been no more than functions that
happen to live in classes, and they still are. Descriptors are
a red herring here; they're just a generalisation that allows for
some new things. They don't unify anything that was previously
existing but not unified.

The unification I'm talking about is what the *user* sees. Currently
in Python , depending on the method style, you might need obj1.func()
or obj2.func(obj1) depending on the types of obj1 and obj2. This is
unnecessary complexity. It adds nothing to the fundamental
capabilities of the language. All methods and functions *should* look
the same to the user.

For an example of how this *could* be done see the PrototypeSyntax
documents at http://ece.arizona.edu/~edatools/Python/ For an example
of how the presentation of OOP in Python could be cut in half, see the
Prototypes documents linked on that same page.

Ruby and Prothon got it right. There are no special "static methods".
Python should have done the same in its original design. Now it will
take an incompatible change in Python to fix it. I'm hoping this will
be done in Python 3. If not, something like Prothon will eventually
replace Python.

-- Dave
 
J

Jonathan Gardner

Yep. In its purest form, a proto-OO language would have only a single
'type' - object - and no 'classes' at all. While folk who are used to
relying on type/class information to make their programs work may
freak a bit at the thought of this, languages like Python and Ruby
have already demonstrated that 'duck typing' can work well. (Again,
it's mostly just a matter of the developer having a bit of discipline
in the first place than relying on the compiler to pick up their slop
after the event.

I have spent some time thinking about this and looking at my own code.
Isn't it currently discouraged to use "type" to classify objects, and
then depend on the type returned? Instead, we should look at the
actual interface to see if it implements what we need rather than
trying to force it to descend from a particular class.

Shared class data is trivial to implement in a classless system, as
you demonstrated. In fact, so is typing - just have an attribute
called "__class__" and methods for determining if a particular class
is in the inheritance tree of this object's class. We can even go as
far as to implement a system of calling the class's methods or
attributes if they are not present in the object itself. (Looks
familiar? Isn't this the way Python works right now?)

Because implementing the current Python object system in classless
objects is so easy to do, it is apparent that classless objects are a
superset (IE, contain all the features of and perhaps some more) of
classful objects. Therefore, if Python were to approach a classless
object system, it would be enhancing its featureset while being able
to simultaneously maintain backwards compatibility. (At least,
theoretically. I know that the internals of the python interpreter and
run time engine depend heavily on objects behaving the way that they
do.)

The question then becomes: Which is more programmer-friendly: classful
or classless programming?

The only practical limitation is that with classes, you can stuff all
the shared attributes and method into a neat package. However, with
classless, whenever you copy an object, you would have to implement
the behavior of copying all of the available attributes and methods.
How to share that data between multiple copied instances and the
original in an efficient manner is non-trivial.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top