By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,625 Members | 1,283 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,625 IT Pros & Developers. It's quick & easy.

What is good about Prothon?

P: n/a
I'm concerned that with all the focus on obj$func binding, &closures,
and other not-so-pretty details of Prothon, that we are missing what
is really good - the simplification of classes. There are a number of
aspects to this simplification, but for me the unification of methods
and functions is the biggest benefit.

All methods look like functions (which students already understand).
Prototypes (classes) look like modules. This will make teaching OOP
much simpler, especially for the students and professional engineers
(non-CIS) that I am most concerned about. I teach electronic design
tools, not programming. Current plans are to include some basic
Python, no OOP. If I could add OOP with another 4 hours, I would do
it.

I've written a proposal for a prototype syntax that I believe captures
the essense of what is good in Prothon, while not departing too
radically from Python. see PrototypeSyntax.htm at
http://ece.arizona.edu/~edatools/Prothon/ I would like to get
feedback from Python experts on the potential problems with this
syntax. The major question is automatic translation of existing Python
programs to the new syntax. I'm one of those users who would not give
up the existing libraries in Python, no matter how good some
alternative language may be.

I would also like to get feedback from users on what they like or
dislike about this proposal. I will summarize this feedback in the
"Pros and Cons" section of the proposal.

Below are some excerpts from the syntax proposal. Please see the link
above for better formatting.

-- Dave

Proposed Prototype Syntax
=========================
< snip >

Example of Simplified Classes ( Prototypes )
============================================

Animal --> Mammal --> Feline --> Cat
------- ------- ------- -------
numAnimals numMammals numFelines numCats
home genus
__init__() __init__() __init__() __init__()
.sound .sound
.name
show() show() show() show()
talk() talk()
proto Animal(object): # Inherit from the primitive object.
numAnimals = 0
home = "Earth"
....
<see the "OOP Chapter" at http://ece.arizona.edu/~edatools/Prothon/
for the complete example.>
....
proto Cat(Feline):
numCats = 0
__init__ :( n = "unknown", s = "Meow" ):
Feline.__init__()
Cat.numCats += 1
.name = n # Set instance variables.
.sound = s
show :(): # Define a "static method".
Feline.show()
print " Cats:", Cat.numCats
talk :():
print "My name is ...", .name
print "I am a %s from %s" % (.genus, .home)
Mammal.talk() # Call an unbound function.
print __self__ ### Diagnostic check.

cat1 = Cat() # Create instance.
with cat1: # Modify instance variables.
home = "Tucson"
genus = "feline"
name = "Garfield"
cat1.talk() My name is ... Garfield
I am a feline from Tucson
Mammal sound: Meow
<__main__.Cat object at 0x00A894B0>


Changes from Current Python
===========================
-- Keyword class is changed to proto.
-- All methods have the same form, identical to a simple function.
-- Function header lines are re-arranged. def --> : Parentheses are
optional.
-- self is replaced with a leading dot, and eliminated from the arg
list.
-- Current instance is available if ever needed via __self__
-- Instances can have their attributes modified in a with block.

Benefits of Proposed Syntax
===========================
-- Unification of all function forms ( bound, unbound, static, class,
lambda ). All will have the same form as a normal function
definition. This will make it easier to teach OOP. Students will
already understand functions and modules. OOP is a small step up. A
prototype will look just like a module ( except for the instance
variables ). See Parallels between Prototypes and Modules below.

-- Using an explicit __self__ variable avoids the magic first
argument, and makes it easier to explain instance variables. See the
sections below comparing a brief explanation of instance variables in
Python vs the simplified form. A full presentation of OOP, like pages
295-390 in Learning Python, 2nd ed. will likely be 1/2 the number of
pages. Not only is the basic presentation simpler, but we can
eliminate a lot of discussion of lambda functions, static methods,
etc.

-- All attributes of a prototype ( both data and functions ) will be
in a neat column, making it easier to find a particular attribute when
visually scanning a program. Understanding the structure of a program
will be almost as quick as seeing a UML diagram.

-- Lambda keyword will be gone. An anonymous function using normal
function syntax can be extremely compact. ( :x,y:x+y )

-- Method definitions will be less cluttered and less typing with
__self__ as a hidden variable.

-- Changing numerous attributes of an instance will be more
convenient. ( need use case )

-- Migration of Python programs to Prothon will be automatic and
reliable. ???

Pros and Cons of the Proposed Syntax
====================================
Classlessness

Con: The proposed syntax is not purely classless. This is important
because ... ???

Unification of Methods and Functions

Pro1: Less to learn.

Con1: Experts don't care. Beginners don't need advanced method
syntax.

Pro2: Replace lambdas with standard function syntax.

Con2: ???

Explicit __self__

Pro1: Allows the unification of methods and functions.

Con1: ???

Pro2: Explanation of instance variables is simpler.

Con2: Using __self__ instead of a special first argument is less
explicit.

Pro3: Less typing and less clutter in method definitions.

Con3: Can use "s" or "_" instead of "self" to minimize typing and
clutter.

"Assignment" Syntax for Function Definitions

Pro1: See all the variables at a glance in one column.

Con1: ???

Pro2: Emphasize the similarity between data and functions as
attributes of an object.

Con2: ???

Symbol instead of def Keyword

Pro: Allows lambda functions to be included in the unification.

Con: Symbols are never as clear as keywords.

With Block

Pro: Saves typing the object name on each line.

Con: Making it too easy to modify prototypes after they have been
created will lead to more undisciplined programming.

Issues relevant to teaching OOP
===============================
Parallels between Prototypes and Modules
----------------------------------------
Ninety percent of what students need to know about prototypes is
already understood from their study of functions and modules. Even
some tricky issues are best explained by comparing to a parallel
situation with modules.
< snip >

Explanation of Instance Variables in Python
-------------------------------------------
""" Some of the variables inside the functions in a class have a
self. prefix. This is to distinguish local variables in the function
from "instance variables". These instance variables will be found
when the function is called, by searching the instance which called
the function. The way this works is that calling the function from an
instance causes that instance to be passed as the first argument to
the function call. So if you call cat1.talk(), that is equivalent to
Cat.talk(cat1) If you call cat1.set_vars( "Garfield", "Meow"), that is
equivalent to Cat.set_vars(cat1, "Garfield", "Meow")

The "current instance" argument is auto-magically inserted as the
first argument, ahead of any other arguments that you may provide in
calling a method that is "bound" to an instance. Note: The
distinction between instances and classes is important here. If you
call a function from a class, that function is not bound to any
instance, and you have to supply the instance explicitly in the first
argument ( Cat.talk(cat1) )

The variable name self is just a convention. As long as you put the
same name in the first argument as in the body of the definition, it
can be self or s or even _ The single underscore is handy if you
want to maximally suppress clutter. """

Explanation of Simplified Instance Variables
--------------------------------------------
""" Some of the variables inside the functions in a prototype have a
leading dot. This is to distinguish local variables in the function
from "instance variables". When a function is called from an instance
( cat1.talk() ) a special global variable __self__ is automatically
assigned to that instance ( __self__ = cat1 ) Then when the function
needs an instance variable ( .sound ) it uses __self__ just as if you
had typed it in front of the dot ( __self__.sound ) The leading dot
is just an abbreviation to avoid typing __self__ everywhere. """

========== END ==============

Jul 18 '05 #1
Share this Question
Share on Google+
28 Replies


P: n/a

"David MacQuigg" <dm*@gain.com> wrote ...
I'm concerned that with all the focus on obj$func binding


I would like to point out, as a technical detail, you will quickly find out
when you implement "your" Prothon, as I did in "my" Prothon, and Lenard
Lindstrom did in his Python implementation of "his" Prothon, that you MUST
focus on function/method binding on objects. This is where the
classlessness of Prothon versus classfulness of Python exhibits its
differences.

Ignoring the problem of calling the ancestor's version of a method by just
using the same old obj.func() will not work. You don't have to use the
current suggestion of obj$func() (we Prothonites may not use it either), but
you cannot live in denial about the need for it.
Jul 18 '05 #2

P: n/a
David MacQuigg wrote:
....
All methods look like functions (which students already understand).

I think it might be more proper to say that you've made all functions
methods with an implicitly defined target, but I suppose the statement
is still technically true.
Benefits of Proposed Syntax
===========================
-- Unification of all function forms ( bound, unbound, static, class,
lambda ). All will have the same form as a normal function
definition. This will make it easier to teach OOP. Students will
already understand functions and modules. OOP is a small step up. A
prototype will look just like a module ( except for the instance
variables ). See Parallels between Prototypes and Modules below.

This is nice. Not "I'm going to rush out to adopt a language because of
it" nice, but nice enough. I'm curious about one thing:

proto x( object ):
flog :( x, y ):
.x = x
a = x()
b = x()
a.flog = b.flog
a.flog()
print b.x

In other words, how do I hold a reference to a bound method/function if
there are no such things and only the "last access" determines what the
implicit target is? Just to be clear, I'm assuming you're going to have
storage *somewhere* so that:

a = module.do
a()

works.
-- Using an explicit __self__ variable avoids the magic first
argument, and makes it easier to explain instance variables. See the
sections below comparing a brief explanation of instance variables in
Python vs the simplified form. A full presentation of OOP, like pages
295-390 in Learning Python, 2nd ed. will likely be 1/2 the number of
pages. Not only is the basic presentation simpler, but we can
eliminate a lot of discussion of lambda functions, static methods,
etc.

This is a wash IMO, with the explicit "self" having a slight edge on
"Explicit is better than Implicit" grounds. You now have to explain
where the magic __self__ comes from instead of how self is bound when
you access the instance's method. They're both magic, the Python stuff
is just explicitly visible. Still, since you're coding it deep into
this new language, it'll be first nature to the Whateverthon programmer.

On a personal note, the moment where I "got" the concept of methods
(Python was my first OO language) was seeing "self" in the argument list
of a function and realising that it's just a parameter curried into the
function by doing x.method lookup. That is, it just looked like any
other function, the parameter was just a parameter, nothing special,
nothing requiring any extra knowledge save how it got bound (and that's
pretty darn simple). Coming from a structures+functions background it
made complete sense.
-- All attributes of a prototype ( both data and functions ) will be
in a neat column, making it easier to find a particular attribute when
visually scanning a program. Understanding the structure of a program
will be almost as quick as seeing a UML diagram.

Can't say I find it particularly compelling as an argument, not if
introducing punctuation-itis is the cost, anyway. Most people I know
use syntax colouring editors, after all.
-- Lambda keyword will be gone. An anonymous function using normal
function syntax can be extremely compact. ( :x,y:x+y )

That particular example almost screams "don't do this", doesn't it?
:(x,y): x+y I can see as an improvement, but yawn, really. Making
function definitions expressions rather than statements would have the
same effect. By the way, how do you know when your lambda is finished?
I gather the ()s are required if using as an expression?
-- Method definitions will be less cluttered and less typing with
__self__ as a hidden variable.

I personally prefer explicit to implicit, but I know there's lots of
people who are big into saving a few keystrokes.
-- Changing numerous attributes of an instance will be more
convenient. ( need use case )

That's nice, but honestly, if you're doing a lot of this in cases
trivial enough to warrant the addition you should likely be refactoring
with a domain-modelling system anyway. Still, if you modify the with to
work something like this:

with x:
.this = 32
.that = 43
temp = 'this'*repeat
.something = temp[:55]

i.e. to just alter the implicit target of the block, not force all
variables to be assigned to the object, it seems a nice enough feature.
Pro2: Replace lambdas with standard function syntax.

Con2: ???

Fine, but no need to redefine the spelling for that save to make the
definition itself an expression that returns the function as a value and
allows one to drop the name. i.e. a = def ( y,z ): y+z would work just
as well if you could assign the result to a variable and figured out how
you wanted to handle the indentation-continuation thing to know when the
function ended.
Explicit __self__

Pro1: Allows the unification of methods and functions.

Con1: ???

Is hidden (implicit) magic that requires the user to learn rules as to
what the target is when treating functions/methods as first-class
objects. Not a big deal, really.
Pro2: Explanation of instance variables is simpler.

Con2: Using __self__ instead of a special first argument is less
explicit.

Um, can't say I see this as a huge pedagogical win. A function either
takes an argument self and can set attributes of the object, or a
function has access to a magical "global" __self__ on which it can set
attributes. I'll agree that it's nice having the same concept for
module and class variables, but seeing that as a huge win assumes, I
think, that those being taught are coming from a "globals and functions"
background rather than a structures and functions background. One type
is accustomed to altering their execution environment, the other to
altering solely those things which are passed into the function as
parameters.
Pro3: Less typing and less clutter in method definitions.

Con3: Can use "s" or "_" instead of "self" to minimize typing and
clutter.

That's a counter, not a con. Similarly "Explicit is better than
Implicit" is only a counter, not a con. A con would be: "presence of
variable of implicit origin" or "too much punctuation". Don't think
either is a huge concern.
"Assignment" Syntax for Function Definitions

Pro1: See all the variables at a glance in one column.

Con1: ???

Doesn't seem a particularly strong pro. IOW seems pretty minimal in
benefit. As for a con, the eye, particularly in a syntax-colouring
editor picks out keywords very well, while punctuation tends to blur
into other punctuation.
Pro2: Emphasize the similarity between data and functions as
attributes of an object.

Con2: ???

I see the pro, seems approx. the same to me.
With Block

Pro: Saves typing the object name on each line.

Con: Making it too easy to modify prototypes after they have been
created will lead to more undisciplined programming.

As specified, makes it only useful for trivial assignments. If you're
going to all the trouble of introducing .x notation to save keystrokes,
why not simply have with alter __self__ for the block so you can still
distinguish between temporary and instance variables?

In the final analysis, this really seems like about 3 separate proposals:

* I like the .x notation's universal applicability, it does seem
simple and elegant from a certain point of view
o I don't like the implicit __self__, but that's an integral
part of the proposal, so a wash
o I'd want clarification of how to store a reference to
another object's (bound) method (which is *extremely* common
in Python code for storing, e.g. callbacks)
* I really dislike the :( ): function definition notation,
"Readability Counts". Why clutter the proposal with that?
* I'm neutral on the with: stuff, I'd much prefer a real block
mechanism similar to Ruby with (if we're using implicit targets),
the ability to specify the .x target for the block

So, the .x notation seems like it would be nice enough, but nothing else
really makes me jump up and down for it...

That said, I'd probably be willing to use a language that was running on
the PythonVM with a parser/compiler that supported the syntax. I'd be
totally uninterested in automated translation of Python code to the new
form. That's the kind of thing that can be handled by running on the
same VM just as easily as anything else and you then avoid lots of
migration headaches.

So, just as a marketing data-point; I'm not convinced that this is
markedly superior, but I'd be willing to try a language that differed
from Python in just the .x aspects to see whether it was worthwhile.

Have fun,
Mike

_______________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://members.rogers.com/mcfletch/

Jul 18 '05 #3

P: n/a

"Mike C. Fletcher" <mc******@rogers.com> wrote...
I'd want clarification of how to store a reference to
another object's (bound) method (which is *extremely* common
in Python code for storing, e.g. callbacks)
* I really dislike the :( ): function definition notation,
"Readability Counts". Why clutter the proposal with that?
* I'm neutral on the with: stuff, I'd much prefer a real block
mechanism similar to Ruby with (if we're using implicit targets),
the ability to specify the .x target for the block


For what it's worth, you are basicly in agreement with the current proposals
for Prothon.
Jul 18 '05 #4

P: n/a
Mark Hahn wrote:
....
For what it's worth, you are basicly in agreement with the current proposals
for Prothon.

Maybe I should add designing languages to my list of projects starved
for time :) .

Have fun,
Mike

_______________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://members.rogers.com/mcfletch/

Jul 18 '05 #5

P: n/a

"Mike C. Fletcher" <mc******@rogers.com> wrote ...
Maybe I should add designing languages to my list of projects starved
for time :) .


We'd love to have you...
Jul 18 '05 #6

P: n/a
On Mon, 26 Apr 2004 12:36:51 -0700, "Mark Hahn" <ma**@prothon.org>
wrote:
<snip>
Ignoring the problem of calling the ancestor's version of a method by just
using the same old obj.func() will not work. You don't have to use the
current suggestion of obj$func() (we Prothonites may not use it either), but
you cannot live in denial about the need for it.


I'll take this as a
Question: How does the iterpreter know that Mammal.talk is an unbound
function and not a new binding to Mammal?

Answer: For reference, I have marked the line in question with !!!

proto Cat(Feline):
numCats = 0
__init__ :( n = "unknown", s = "Meow" ):
Feline.__init__()
Cat.numCats += 1
.name = n # Set instance variables.
.sound = s
show :(): # Define a "static method".
Feline.show()
print " Cats:", Cat.numCats
talk :():
print "My name is ...", .name
print "I am a %s from %s" % (.genus, .home)
Mammal.talk() # Call an unbound function. <== <== !!!
print __self__ ### Diagnostic check.

I am assuming the same implicit rule that Python follows. Mammal is a
prototype (class). When you access a function from a class in Python,
you get an unbound function. When you access that same function from
an instance, you get a function bound to that instance.
cat1 = Cat("Garfield","Meow")
cat2 = Cat("Fluffy","Purr") bf = cat1.talk # function Cat.talk bound to cat1
bf <bound function Cat.talk of <__main__.Cat object at 0x00A83D10>> bf() My name is ... Garfield
I am a feline from Earth
Mammal sound: Meow
<__main__.Cat object at 0x00A83D10>
uf = Mammal.talk # unbound function
uf <unbound function Mammal.talk>

In the rare situation where we need to explicitly change the current
instance: __self__ = cat2
uf() Mammal sound: Purr


Python's syntax does violate the "Explicit" rule, but it seems in this
case the "Practicality" rule over-rides. By making the function bound
or unbound, depending implicitly on the type of the object before the
dot, Python has avoided the need for an explicit binding syntax.

If we could come up with an explicit binding syntax that was not a
burden on either readability or clarity, then I would vote for a
change. To summarize the current proposals:

Prothon:
$var # var is attribute of self
^var # var is an attribute of a proto of self
obj.func() # func is an attribute of obj and bound to obj
obj$func() # func is an attribute of obj and bound to current self
x = obj.func # x is bound method of func attribute of obj and obj
x = obj$func # x is bound method of func attribute of obj and self
x = obj.attr(func) # x is unbound func

Python 3:
bf = cat1.talk # bound function
uf = Cat.talk # unbound function
bf() # call a bound function
uf() # call unbound function with current __self__

__self__ = cat2 # change __self__ ... rarely needed
uf() # call with cat2

The "Python 3" proposal follows current Python syntax except for the
use of a global __self__ variable instead of a special first argument.

-- Dave

Jul 18 '05 #7

P: n/a

"David MacQuigg" <dm*@gain.com> wrote ...
Mammal.talk() # Call an unbound function. <== <== !!!


This works great in Python, but in Prothon there is no such thing as a class
to tell the difference in the binding. The concept of a prototype is in the
programmer's mind, not the interpreter's, since every object can be a
prototype.

Feel free to make this an argument for Python 3, but quit comparing your
proposal to Prothon since it is not Prothon compatible.

You have argued this in the Prothon mailing lists for almost a month with
Greg and me. Please don't just start it up again here (about Prothon I
mean).
Jul 18 '05 #8

P: n/a
> David MacQuigg wrote:
Mammal.talk() # Call an unbound function. <== <== !!!

Mark Hahn wrote: This works great in Python, but in Prothon there is no such thing
as a class to tell the difference in the binding. The concept of a
prototype is in the programmer's mind, not the interpreter's,
since every object can be a prototype.


I thought you'd already solved the problem anyway?

Given an object named 'obj' and a function attribute in that object named
'func':

obj.func # bound method
obj('func') # unbound function
obj$func # function bound to $ (self), e.g. for super calls

-Mike
Jul 18 '05 #9

P: n/a

"Michael Geary" <Mi**@DeleteThis.Geary.com> wrote ...
I thought you'd already solved the problem anyway?


David has been insisting for weeks that we don't need the obj$func() form if
the interpreter just recognizes that obj is a prototype as Python does with
classes. This is a never-ending argument that I am trying to end,
especially since he has been using his argument to make claims about Prothon
being too complex.

I've got Has on one side of me who says that having prototype references
instead of copies makes it too much like Python and therefore it isn't
prototype-based and then David who thinks prototypes should be handled
internally like classes (which would actually make them classes) and an
occasional Lisper who thinks Prothon should be like Lisp. I knew I couldn't
please them all, but I thought I'd be able to please one or two :)
Jul 18 '05 #10

P: n/a
has
David MacQuigg <dm*@gain.com> wrote in message news:<bn********************************@4ax.com>. ..
Example of Simplified Classes ( Prototypes )
============================================


[SNIP]

Class-based OOP by any other name. But then, I've pointed this out
already. See Emperor, clothes; lack of.

Here; while I don't claim them to be paragons of programming, I
suggest taking a look at my old AppleScript libraries at
<http://applemods.sourceforge.net/>. (Note: scripts are compiled, so
you'll need a Mac to view source.) See Types, HTMLTemplate and ASTest
for examples of OO programming that isn't class-fixated. Might lend
some useful perspective.
Jul 18 '05 #11

P: n/a
has wrote:
(Note: scripts are compiled, so you'll need a Mac to view source.)


Can you at least make a screen snapshot available or something for the "rest
of us"?
Jul 18 '05 #12

P: n/a
On Tue, 27 Apr 2004 09:12:11 -0700, "Mark Hahn" <ma**@prothon.org>
wrote:
You have argued this in the Prothon mailing lists for almost a month with
Greg and me. Please don't just start it up again here (about Prothon I
mean).


Mark, Stop making false statements about me. If you have personal
criticism, send me an email.

You now have 5 out of 9 postings on this thread. I don't have time to
keep up with this, so anyone following this thread please don't take
my lack of further response as lack of interest in your feedback. My
filter is set to ignore "Prothon" in the subject line.

Please join me on the new thread "Ideas for Python 3".

-- Dave
Jul 18 '05 #13

P: n/a
On Tue, 27 Apr 2004, Mark Hahn wrote:
I knew I couldn't please them all, but I thought I'd be able to please
one or two :)


Big mistake! Set out only to please yourself! After all, this is your
itch...

--
Andrew I MacIntyre "These thoughts are mine alone..."
E-mail: an*****@bullseye.apana.org.au (pref) | Snail: PO Box 370
an*****@pcug.org.au (alt) | Belconnen ACT 2616
Web: http://www.andymac.org/ | Australia

Jul 18 '05 #14

P: n/a
Mike,

Thanks for a very thorough and thoughtful review of this
proposal. Please see my responses in the thread "Ideas for Python 3".

-- Dave
Jul 18 '05 #15

P: n/a
has
"Mark Hahn" <ma**@prothon.org> wrote in message news:<oiCjc.9622$Qy.6230@fed1read04>...
has wrote:
(Note: scripts are compiled, so you'll need a Mac to view source.)


Can you at least make a screen snapshot available or something for the "rest
of us"?


Eh, I'll see what I can do. Here's a short example to get you started:
on makeStack()
script
property class : "Stack"
property _linkedList : missing value
-------
on push(val)
script node
property nval : val
property chain : _linkedList
end script
set _linkedList to node
return
end push
--
on top()
if _linkedList is missing value then error "Can't get top:
stack is empty." number -1728
return _linkedList's nval
end top
--
on pop()
if _linkedList is missing value then error "Can't pop:
stack is empty." number -1728
set val to get _linkedList's nval
set _linkedList to get _linkedList's chain
return val
end pop
--
on isEmpty()
return (_linkedList is missing value)
end isEmpty
end script
end makeStack

-- TEST

set foo to makeStack()
foo's push(3)
foo's push(5)
log foo's pop() --> 5
log foo's pop() --> 3

In AS, every compiled script is itself a script object. Scripts can be
loaded into other scripts using the 'load script' command; this
provides the foundation for library-based design. Script objects can
also be declared within other script objects and handlers (aka
procedures) using the 'script [identifier]...end script' block. This,
along with their support for delegation via the 'parent' property,
allows you to do prototype-based OOP. Incidentally, because script
objects have first-class syntactic support, they also support modular
design within a single file, sectioning off parts as separate
namespaces without having to move code off into separate files as
you'd do in Python; e.g.:

----- begin script (global namespace) -----

property foo : 0

script Sub_Namespace1
-- properties and handlers here
end

script Sub_Namespace2
-- properties and handlers here
end

on bar()
...
end bar

----- end script -----

(e.g. This ability makes for a very handy halfway stage when
refactoring one file into several or vice-versa.)

Thus a single, very generic type (script) can perform all the roles
that it takes Python several specialised and largely
non-interchangeable types (classobj, instance, module) to do. It's
such a clean, simple and extremely flexible way to do encapsulation
that, though I can understand why more static languages might require
the extra layers and complexity, I've never understood why languages
like Python, Smalltalk, etc. feel such need to erect all these extra
hurdles for themselves. Maybe they just like making work for
themselves? Of course, greater freedom also implies greater
responsibility and a better understanding of what you're trying to
achieve, which might freak some folk from the BDSM school of
programming, but that's their problem - and loss.

Other nice stuff: while AS allows only a single delegate per object,
the ability to compose object behaviour at runtime makes it much more
powerful than class-based single inheritance, and less of a PITA to
use than MI. Just create and delegate-chain together the objects you
want as and when you need them.

e.g. I used this approach in my original HTMLTemplate library to
construct the various template objects - see
<http://freespace.virgin.net/hamish.sanderson/TemplateConstructors.rtf>
for the relevant module (forgive the nasty source code-munging bit in
the middle, but one of AS's limitations is an inability to add/remove
slots once an object is created*). Compare this with the Python port
where I had to use MI to compose behaviour
<http://freespace.virgin.net/hamish.sanderson/htmltemplate.html> -
particularly the older 0.3.2 release where I managed to spaghetti the
inheritance tree something awful on my first attempt (I had no such
problems designing the AS version where composing objects was a
no-brainer).

[* Python shouldn't feel too smug, however, seeing as I had no better
luck trying to dynamically attach property objects to class instances,
and had to resort to sticking nodes into a private dict accessed via
__getattr__ and __setattr__.]

Obviously, there's some things about the AS implementation that don't
translate well to a more Python-like language design: e.g. its use of
object-centric Smalltalk/Obj-C-style message passing instead of
Python-style bound functions make callbacks a bit of a chore (you have
to pass the entire script object around rather than just a function
object/pointer), and its lexical/dynamic variable scoping is a bit of
a disaster area (though that may simply be down to poor implementation
than fundamental design limitation).

What's important is just to note the extreme simplicity and total lack
of "sophistication" in its script object system; it may be a little
_too_ simple for an industrial-size language, but it's a heck of a lot
easier to start with an overly simple but clean and coherent model and
build upward than begin with something that's over-complex and muddled
and try to clean it up. Good programmers know how to add features;
great ones know how NOT to.
Jul 18 '05 #16

P: n/a
has
"Mark Hahn" <ma**@prothon.org> wrote in message news:<hzwjc.6087$Qy.2366@fed1read04>...
I've got Has on one side of me who says that having prototype references
instead of copies makes it too much like Python and therefore it isn't
prototype-based


Not so. I've been saying it's not a proto-OO language because proto-OO
behaves according to a single tier model where all objects are equal,
whereas Prothon, like class-based OO languages, follows a two-tier
model where some objects (classes/"prototypes") are more equal than
others ("object" objects).

I may not know much about programming, but I've a pretty damn good eye
on me and can well tell the difference between stuff that's genuinely
simple and stuff that merely thinks it is. I know how high to set the
bar and, unlike some "real" programmers who think "simplicity" is
something you can get from slapping an extra abstraction layer on top
of the current complexity, I'm not afraid to rip everything down and
start right over again if something fails to reach it; and keep doing
so till it does. (Something a fair few professionals have yet to
learn, IMHO.)

You've asked for input on Prothon and FWIW I've given it. And while
it's no skin off my nose whether you want/need/like it or not, I'd
rather you didn't make it sound like the above is the best argument I
could muster as it's a little embarrassing. (Yeah, I realise that
sifting the wheat of my posts from the plentiful chaff can take some
work, but hey, nothing in life worth doing is easy...)
Jul 18 '05 #17

P: n/a
has wrote:
"Mark Hahn" <ma**@prothon.org> wrote in message
news:<hzwjc.6087$Qy.2366@fed1read04>...
I've got Has on one side of me who says that having prototype
references instead of copies makes it too much like Python and
therefore it isn't prototype-based


Not so. I've been saying it's not a proto-OO language because proto-OO
behaves according to a single tier model where all objects are equal,
whereas Prothon, like class-based OO languages, follows a two-tier
model where some objects (classes/"prototypes") are more equal than
others ("object" objects).


I apologize. I accidently stated what I once thought you were claiming. I
do know now that you are claiming that it's not prototype based if it is
two-tiered with templates and instances.

My position (which is basicly in agreement with Lieberman's paper) is that
having multiple tiers is inherent in all programming and is a natural result
of factoring the problem of making many copies of the same thing.

We will continue to agree to disagree. I have learned a lot in my arguing
with you though and do appreciate the time you've spent wearing out your
keyboard.

You might be interested to know that the first benefits of classlesness are
starting to appear in Prothon, however minor. A small example is that in my
Pickle replacement (called Prosist) instead of having a Prototype called DB
that you load with the Prosist module to instantiatate your db, you can use
the module object itself as the prototype:

# typical Python setup
import Pickle
db = Pickle.DB("filename.db")

# Prothon
import Prosist
db = Prosist("filename.db")

I know it's tiny, but it's a beginning to show how things can be simpler
when you don't have to have classes. Maybe you could show how your one-tier
approach would make this even simpler?
Jul 18 '05 #18

P: n/a
has
"Mark Hahn" <ma**@prothon.org> wrote in message news:<ZHXjc.17225$Qy.13377@fed1read04>...
My position (which is basicly in agreement with Lieberman's paper) is that
having multiple tiers is inherent in all programming and is a natural result
of factoring the problem of making many copies of the same thing.
And my position is that:

1. Anyone can find pieces of paper to prop up an existing position. It
doesn't really prove anything. It's finding pieces of paper that
actively contradict your position and being able to A. convincingly
refute their arguments or, if that fails, B. acknowlege that they're
right and you're wrong, and revise your position accordingly.

2. There's a world of difference between the user imposing their own
tiers upon an environment, and having the environment impose its
choice of tiers upon them. Tiers can add convenience, which is what
makes them tempting in the first place, but they also add
restrictions. Adding tiers is easy; it's removing them that's hard.

3. Factoring's supposed to add simplicity, not complexity. Programmers
are far too tolerant - sometimes even welcoming - of the latter. An
attitude I think goes a long way to explaining why so much software is
so damned complicated: there's simply not enough lazy, intolerant,
impatient folk in software development. (Note: being lazy, intolerant
and impatient, as well as somewhat slow-witted, I shall no doubt be
doing my bit to redress this in future.;)
<SIDENOTE>
For benefit of viewers who've just tuned in, here's a practical
illustration of how Prothon freaks me out: let's say I want to create
three objects; a, b and c. In AppleScript, I would do this:
-- Create object 'a'
script a
property x : 1
end script

-- Create objects 'b' and 'c'
copy a to b
copy a to c

log {a's x, b's x, c's x} --> {1, 1, 1}

set b's x to 4
log {a's x, b's x, c's x} --> {1, 4, 1}

set a's x to 9
log {a's x, b's x, c's x} --> {9, 4, 1}
[note: AS's 'copy' command performs a deep copy; unlike Python's,
which is shallow]

Whereas Prothon does this:
# Create object 'a'
a = Object()
a.x = 1

# Create objects 'b' and 'c'
b = a()
c = a()

print a.x, b.x, c.x # --> 1 1 1

b.x = 4
print a.x, b.x, c.x # --> 1 4 1

a.x = 9
print a.x, b.x, c.x # --> 9 4 9
In AS, a, b, and c are all equivalent and independent; any changes
made to one do not affect the others. It's a no-brainer to use, and
quite safe. In Prothon, b and c derive state and behaviour from a
unless/until it's modified locally (ie on b or c). Changes made to one
may or may not show up in another depending on the derived
relationship and subsequent changes*, and it's up to the user to keep
track of all this - IMO a great way for all sorts of unpleasant,
unwanted interaction bugs to crop up in non-trivial code unless you're
very, very careful. (And hey, I've already got C pointer arithmetic
any time I feel like living dangerously.;)

(* In class-based OO you've also got the potential to do this kind of
data sharing, but there the difference between sharers - i.e. classes
- and sharees - i.e. instances - is explicit, so casual mix-ups are
much less likely to happen.)

</SIDENOTE>

We will continue to agree to disagree.
Think I'll just continue to disagree, if it's all the same.

I have learned a lot in my arguing
with you though and do appreciate the time you've spent wearing out your
keyboard.


Well I'm glad it wasn't completely wasted. And hey, who knows; you may
always change your mind. (And I have some neat thoughts on how to set
up a nice modules system if you ever tempt me back...;)
Jul 18 '05 #19

P: n/a
has wrote:
# Create object 'a'
a = Object()
a.x = 1

# Create objects 'b' and 'c'
b = a()
c = a()


You've mistranslated your example. The Prothon equivalent
would be more like

b = a.copy()
c = a.copy()

and then you have three independent objects, just as you
want.

The exactly equivalent thing can also be done in Python,
for what its' worth.

--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Jul 18 '05 #20

P: n/a
has wrote:
In AS, a, b, and c are all equivalent and independent; any changes
made to one do not affect the others. It's a no-brainer to use, and
quite safe. In Prothon, b and c derive state and behaviour from a
unless/until it's modified locally (ie on b or c). Changes made to one
may or may not show up in another depending on the derived
relationship and subsequent changes*,
I told you before that we had a Self-like copy and asked you then if using
that would make you happy. You never answered that question. Now you've
posted an example that ignores the Prothon copy (yes, it is spelled exactly
like the AS copy :)

Will you only be happy with Prothon if I rip out everything that is not like
AS or Self? Isn't having Prothon capable of doing everything AS and Self
can do, in the same way they do it, good enough for you? I know for a fact
that it can do everything they can do because there are months left in the
design and if you just got rid of that chip on your shoulder and pitched in
and helped, it could work well for people who want to use it like you do.

You should be aware that we are discussing right now the possibility of
putting the whole "class-mimicing" structure on an object that is a
descendent of a pure Self-like root object. Lenard is doing a pretty good
job of explaing to me why we sometimes need objects without the "class-like"
methods __new__ and __init__. Here is his response to my question about
that ("Object" is the "pure" object and "buildable" would have __new__ and
__init__):

------ Beginning of Lenard Lindstrom's post ------
This is all very logical and I have no problem with it, but can you give me a usage example of an object that would inherit directly from Object instead of Buildable?


I do not know about a specific usage example, but knowledge bases in
artificial
intelligence comes to mind as a general case:

object ClydeLike(Object):
$colour = "grey"
$legcount = 4
$mass = 2500

object Clyde(ClydeLike): # Lieberman got it wrong. I can explain in a
separate posting.
pass

object Fred(ClydeLike):
$mass = 2400

Probably anything whose attributes are initialized to contants, that is, no
calculations
are required. Then specific initial attribute values for an extension object
are set
with the object statement.

If descriptors are implemented in Prothon then value checks and special
computations
can be done on a per attribute bases, removing one more need for an _init_
function.
The Buildable prototype would come into play for immutables and objects that
convert
several input values into a different internal representation at creation
time.

---------- End of Lenard Lindstrom's post ------------

Lenard even said "Lieberman got it wrong." See! If you come over and help
out there are other like-minded people to work with you

By the way, the above code samples are from current builds of Prothon. The
object keyword was added recently.


Jul 18 '05 #21

P: n/a
has wrote:
Eh, I'll see what I can do. Here's a short example to get you started:
This is plenty. I'm getting a good idea of what is going on here.
In AS, every compiled script is itself a script object. Scripts can be
loaded into other scripts using the 'load script' command; this
provides the foundation for library-based design.
I see no difference from a Prothon module so far (which is good).
Script objects can
also be declared within other script objects and handlers (aka
procedures) using the 'script [identifier]...end script' block. This,
along with their support for delegation via the 'parent' property,
allows you to do prototype-based OOP.
Oh, so the script is also the function. That is a bit limiting, not having
functions within a script.
Incidentally, because script
objects have first-class syntactic support, they also support modular
design within a single file, sectioning off parts as separate
namespaces without having to move code off into separate files as
you'd do in Python;
This I REALLY like. I'll put this on the list of ideas to "steal" for
Prothon.
Thus a single, very generic type (script) can perform all the roles
that it takes Python several specialised and largely
non-interchangeable types (classobj, instance, module) to do.
Prothon is the same. Using a module as a prototype is a trick that recently
paid off. We have no structure or rules making one object unable to play
the role of another. As we slowly unwind our brains from class-thinking
(not an easy task) I expect the benefits to pour forth.
Other nice stuff: while AS allows only a single delegate per object,
the ability to compose object behaviour at runtime makes it much more
powerful than class-based single inheritance, and less of a PITA to
use than MI. Just create and delegate-chain together the objects you
want as and when you need them.
You don't have to convince me that dynamic delegation is good.
[* Python shouldn't feel too smug, however, seeing as I had no better
luck trying to dynamically attach property objects to class instances,
and had to resort to sticking nodes into a private dict accessed via
__getattr__ and __setattr__.]
We'll make sure Prothon can feel smug in this regard.
Good programmers know how to add features;
great ones know how NOT to.


I will be sure to remember that after Prothon is designed. Right now we are
not adding features to Prothon, we are designing version 0.1. You have to
add features when you start with zero features. Even you must admit a
language with zero features is unintresting :)
Jul 18 '05 #22

P: n/a
has
Greg Ewing <gr**@cosc.canterbury.ac.nz> wrote in message news:<c6************@ID-169208.news.uni-berlin.de>...
# Create objects 'b' and 'c'
b = a()
c = a()


You've mistranslated your example.


Not at all. I was arguing these issues long before Prothon got its
copy() method. I'm aware of its recent addition, but it doesn't
really change anything: the canonical Prothon way to create new
objects is still b = a(), not b = a.copy().

[FWIW, at least Prothon's not as confusing as Io, whose misleadingly
named "clone()" doesn't in fact clone at all, but does the
make-new-empty-object-that-delegates-to-the-existing-one thing that
Prothon's __call__ does.]
Anyway, this leads me to my next question: how many ways should one
need to create new objects? I now count three in Prothon, which is
certainly one too many. And what's it going to do about it?

The art of great software design isn't adding features, it's getting
rid of them.
Jul 18 '05 #23

P: n/a
has
"Mark Hahn" <ma**@prothon.org> wrote in message news:<Awlkc.36778$Qy.19874@fed1read04>...
has wrote:
In Prothon, b and c derive state and behaviour from a
unless/until it's modified locally (ie on b or c). Changes made to one
may or may not show up in another depending on the derived
relationship and subsequent changes*,


I told you before that we had a Self-like copy and asked you then if using
that would make you happy. You never answered that question. Now you've
posted an example that ignores the Prothon copy (yes, it is spelled exactly
like the AS copy :)


See my other post for the reason why I did this (yes, it was quite
intentional).
But to answer your question directly: no, simply adding a copy()
operation (the "trying to please everybody, and ultimately pleasing
no-one" strategy) won't make me happy; I have no use for another C++.
You might think I'm merely being obtuse; trying to give you a bad day
just for jollies. But no; and perhaps a little digression will help
explain why...

Right now you should be sketching out lots of rough ideas quickly and
in the large, critiquing them, throwing some away, experimenting
further with others, critiquing the results of those tests, revising,
reviewing, refactoring those ideas, compacting and simplifying them,
stripping them down as hard as you can to see just how far you can
simplify them, reversing direction and changing tack; and not letting
yourself get blocked in to a single developmental rat-run where you
can only proceed forward on a single, predetermined path.

Or, in short, for every feature added: 1. justify its addition; and 2.
find at least one other feature - preferably more - that can't
adequately justify theirs and strip them right back out again.

This is another lesson I learnt in art school, btw: when working in
clay, one should always build up. Add a bit of clay, step back,
analyse the result. If you add too much or put it in the wrong place,
don't try to carve it flat or smear it into position; instead, cut the
whole lot right back 'to the bone' and start building it up again.

For me, who learnt this lesson very quickly, it was rather depressing
watching the rest of the class, who didn't, plod away day after day,
fighting a losing battle for hours on end with a material they just
couldn't seem to understand as it turned into a buttery caricature
instead of a portrait head.

Meantime, I'm scooting around the room like a madman, never standing
more than a minute or two in front of my piece before stepping back,
or walking away, or going to get drinks from the vending machine. And
each morning I came in, I'd take a long look with fresh eyes at where
I'd got to the previous day, and if I didn't like it, out came the big
knife as I'd chop great gobs off and throw them back in the clay bin.

I think by the end of that class I'd produced two pretty decent busts,
and had already made a start on the third. The better of the two I
completed within three afternoons too, with the bulk of it done in two
and the third spend mostly idling around and occasionally diving in to
tweak a feature here or there.
Now, wood and stone carving I suck at. You get one chance to get it
right, and if you screw up just once you have to start all over again.
Such fear of failure made me nervous and timid - which, considering
the price of each fresh bit of stone, maybe wasn't entirely
unsurprising - and the results were insipid and flat and utterly,
utterly boring.

But clay I love. It rewards excitement and adventure, and encourages
risk-taking and experimentation; the more bold and daring you are, the
more it becomes alive. If you screw up along the way there's no
permanent loss, and the valuable lessons you gain from doing so _far_
outweigh the cost of any time spent. So you work fast and loose, try
lots of different ideas quickly to see where they might go, screw up
often and learn as much by your mistakes as your successes.
Code is like clay. It's so frustrating for me to see programmers treat
it like stone. If you were in my art class I'd hand you a pile of
newsprint and box of charcoal and have you do 30-second sketches for
an hour. Then another hour doing five-minute drawings. And I can
guarantee the if I then set you to do a finished drawing in the
remaining hour the final result would be far, far better than if I'd
given you a whole day - or even week - to work on it.

--

I'll see if I can get around to answering some of your other questions
later. Meantime, I hope you can find a little time to spend pondering
the above. Who knows, maybe even put what implementation you've done
aside for a bit, and go stroll round the room for a while... maybe
catch some fresh perspective - even surprise yourself. :)
(p.s. My new favourite phrase for the week: "Premature implementation
is the root of all evil." Hope nobody minds!;-)
Jul 18 '05 #24

P: n/a
has wrote:
But to answer your question directly: no, simply adding a copy()
operation (the "trying to please everybody, and ultimately pleasing
no-one" strategy) won't make me happy; I have no use for another C++.


You have a very warped mind. To say that having Python two-tier object
construction and Self-like constructs in the same language is C++ is
ludicrous.

You have finally answered a question I have asked several times. Having
anything but AS or Self in the language will keep you from being happy. Now
that I know where you stand I can quit wasting my time trying to get you to
help out.

You keep pitching that you are such a creative artist, but if you were you'd
be helping find a way to solve the conundrum of merging the Python and Self
worlds and making positive contributions instead of just throwing stones.
Jul 18 '05 #25

P: n/a
In article <CYwkc.44066$Qy.9803@fed1read04>,
"Mark Hahn" <ma**@prothon.org> wrote:
has wrote:
But to answer your question directly: no, simply adding a copy()
operation (the "trying to please everybody, and ultimately pleasing
no-one" strategy) won't make me happy; I have no use for another C++.
You have a very warped mind. To say that having Python two-tier object
construction and Self-like constructs in the same language is C++ is
ludicrous.


He's saying `language that tries to please everybody [by adding
features like copy instead of doing it right in the first place] == C++'
He could have a point. (Is there going to be an optional __copy__
method?)
You have finally answered a question I have asked several times. Having
anything but AS or Self in the language will keep you from being happy. Now
that I know where you stand I can quit wasting my time trying to get you to
help out.

You keep pitching that you are such a creative artist, but if you were you'd
be helping find a way to solve the conundrum of merging the Python and Self
worlds and making positive contributions instead of just throwing stones.


He probably thought they were pearls of wisdom. Guess you don't
want any more, anyway.

Donn Cave, do**@u.washington.edu
Jul 18 '05 #26

P: n/a
Donn Cave wrote:
He's saying `language that tries to please everybody [by adding
features like copy instead of doing it right in the first place] ==
C++' He could have a point. (Is there going to be an optional
__copy__ method?)
Yes, there already is a copy method. It solves the problem he posted of AS
versus Prothon. Adding copy is apparently turning Prothon into C++. I've
never thought of something as simple as copy as being an evil thing. (The
funny thing is I added copy as part of porting Python's methods. It has
nothing to do with Self or AS, but it happens to match his needs).
He probably thought they were pearls of wisdom.
He and I have been going in circles for weeks. I keep trying to get him to
identify what would really make him happy in Prothon and apparently having
anything that resembles the two-tiers of object creation of Python is an
anathema to him and has to be removed. If it stays and there is anything
else in there that he'd like then it would be C++.
Guess you don't want any more, anyway.


Depends on what you mean by pearls of wisdom. I've been getting a lot of
great ideas from both Prothon and Python mailing lists. I've been spending
a lot of time arguing with Has (we started on the Prothon lists) because he
has knowledge of AS and Self and would love to have him contribute. So far
he will only tell me that Prothon sucks because of the two tiers and his
only recommendation is to treat my code like clay and tear it down and start
over.
Jul 18 '05 #27

P: n/a
has
"Mark Hahn" <ma**@prothon.org> wrote in message news:<cSBkc.44739$Qy.16585@fed1read04>...
Donn Cave wrote:
He's saying `language that tries to please everybody [by adding
features like copy instead of doing it right in the first place] ==
C++' He could have a point. (Is there going to be an optional
__copy__ method?)


Yes, there already is a copy method. It solves the problem he posted of AS
versus Prothon.


One: No, it does not. But it does prove _just how little_ of what I've
said you have actually understood.

Two: BTW, learn to differentiate between "ludicrous" and "hyperbole".
They are _not_ the same.

Three: You I was just giving you a hard time for the sake of it? I
wasn't; you asked for criticism, and I gave it. It just wasn't the
criticism you wanted. You want to hear what I say when asked to
critique something I think is a piece of piss but simply don't care
about enough to say? "Yes, that looks very nice/interesting. I'll be
very curious/interested to see how where it goes."

Four: You think it's just you? Obviously you've never seen me chewing
AppleScript a new one; it's such a fundamentally flawed language that
I'm now actually working actively against it. (MacPython-to-AEM
bridge, more hours spent critiquing and reading and learning than I
can shake a stick in, mystery language project in development; hey,
you do the math.)

Five: You think I don't give my own work this treatment? Obviously you
have never seen me spend weeks or months working at something, only to
throw it out the moment I've uncovered a flaw too deep or uneconomic
to fix, or simply discover a new and much simpler way to solve the
same problem, and take all that blood-sweat-and-tears effort and
postmortem then shitcan the lot of it without a second thought. So if
your only reaction to hard criticism is to run away or barricade your
mind to it, if you're not willing to make such sacrifices in the name
of the greater good, if you're not willing to at least entertain the
possibility that You Might Be Wrong Too; then I'm sorry to say but you
really have chosen the wrong line of work to get into, and I can find
much better things to devote all my attention to.

Six: As for what will make me happy? That I never again hear that
bloody Lieberman name used to deflect every criticism I offer. Because
that is so intellectually lazy of you it's actually insulting mine. I
have provided you with plenty of answers throughout; you simply choose
not to notice or accept them. And that is something I absolutely
_cannot_ help you on.
Therefore, I am finally willing to state: "Prothon looks very
nice/interesting. I'll be very curious/interested to see how where it
goes." May you find some fulfillment in that.

has
Jul 18 '05 #28

P: n/a
has
Donn Cave <do**@u.washington.edu> wrote in message news:<do************************@nntp1.u.washingto n.edu>...
He probably thought they were pearls of wisdom. Guess you don't
want any more, anyway.


Yeah, well I'd personally be the first to acknowledge that every other
"pearl" I throw is more commonly a lump of shit. So I actually
appreciate it when folk take a sniff and tell me it's a turd. It's
when they blat every single toss straight into the rough then promptly
ask for another one that I eventually get a bit peeved.

To be honest, however, I've got nobody to blame but myself for this
particular outbreak. I unsubscribed from the prothon mailing list
because I'd already recognised I wasn't getting anywhere and my
continued presence would only waste my own time and energy and
everybody else's. And I should _really_ have known better than to get
re-involved over here. So I apologise to the rest of the
comp.lang.python group - as friendly and civilised an online group as
I've ever been in - for any disturbance caused, and now return you to
your regular program. Let Mark have the last word; just for surviving
me this far I think he deserves it. ;)

Mr Intensity
Jul 18 '05 #29

This discussion thread is closed

Replies have been disabled for this discussion.