What is good about Prothon?

D

David MacQuigg

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"
My name is ... Garfield
I am a feline from Tucson
Mammal sound: Meow

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 ==============
 
M

Mark Hahn

David MacQuigg said:
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.
 
M

Mike C. Fletcher

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/
 
M

Mark Hahn

Mike C. Fletcher said:
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.
 
M

Mike C. Fletcher

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/
 
D

David MacQuigg

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.
My name is ... Garfield
I am a feline from Earth
Mammal sound: Meow
<unbound function Mammal.talk>

In the rare situation where we need to explicitly change the current
instance:
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
 
M

Mark Hahn

David MacQuigg said:
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).
 
M

Michael Geary

Mark said:
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
 
M

Mark Hahn

Michael Geary said:
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 :)
 
H

has

David MacQuigg said:
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.
 
A

Andrew MacIntyre

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

Mark Hahn

has said:
(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"?
 
D

David MacQuigg

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
 
D

David MacQuigg

Mike,

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

-- Dave
 
H

has

Mark Hahn said:
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.
 
H

has

Mark Hahn said:
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...)
 
M

Mark Hahn

has said:
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?
 
H

has

Mark Hahn said:
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.)

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...;)
 
G

Greg Ewing

has said:
# 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.
 

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,981
Messages
2,570,188
Members
46,733
Latest member
LonaMonzon

Latest Threads

Top