Why we will use obj$func() often

M

Mark Hahn

Michael Geary said:
Does anyone have some sample code where obj$func() would be used?
(Apologies if I missed it.)

There have been so many messages about delegation and binding since Greg
originally posted his meowing cat message that it's hard to remember what
the original problem was that Greg pointed out. At that time Prothon had no
solution for the problem. Now there is a released solution but it is
incomplete and has broken the xor operator ( ^ ) (don't tell anyone <grin>).
I'll restate it here in my own way (this is copied from something I posted
on comp.lang.py).

Statement of problem (These are tested programs from released Python and
Prothon:):

# Python

class klass:
def __init__(self):
self.me = 1
def func(self):
print "func1,self"+str(self.me),

class klass2(klass):
def __init__(self):
self.me = 2
def func(self):
klass.func(self) # delegation
print "func2,self"+str(self.me),

inst = klass2()
inst.func() # prints func1,self2 func2,self2

# Directly translated to Prothon

Klass = Object()
with Klass:
.me = 0 # extra line
def .__init__():
.me = 1
def .func():
print "func1,self"+.me,

Klass2 = Klass()
with Klass2:
def .__init__():
.me = 2
def .func():
Klass.func() # does not do what python does
print "func2,self"+.me,

inst = Klass2()
inst.func() # prints func1,self0 func2,self2

As you can see, the call Klass.func() got the function func from the object
Klass and then called it on Klass using Klass as the target "self" instead
of the instance "inst". This is not what Python did and this is the
problem.

In Python the call klass.func() was different because Python knows that
klass is a class and therefore obviously cannot be the target of call (an
instance), so it made the programmer pass the instance self to use as a
parameter.

To fix this, we need to be able to specify in general, what the self object
is going to be during the execution of a function in Prothon (I call this
choice of self "binding self to function" even though it's temporary during
execution).

Greg's solution was to replace the period before the function name in
klass.func() with a different symbol to indicate that the func is not
supposed to be bound to klass as the syntax normally suggests (as in
list.sort!()), but instead defaults to the current self. My final scheme is
almost the same but instead of just defaulting to self, it specifically
forces it to self (this may seem like a semantic difference, but don't say
that to Greg <grin>).

So now we have this solution. Note that delegation to an ancestor prototype
(class in Python), is a common operation, especially in the __init__
function:

Klass = Object()
with Klass:
def $__init__():
$me = 1
def $func():
print "func1,self"+$me,

Klass2 = Klass()
with Klass2:
def $__init__():
$me = 2
def $func():
Klass$func() # voila! problem fixed
print "func2,self"+$me,

inst = Klass2()
inst.func() # prints func1,self2 func2,self2
 
M

Mark Hahn

My apologies. I posted this to c.l.p. by accident. I meant to post this
to Prothon-users.
 
M

Mike C. Fletcher

Mark said:
My apologies. I posted this to c.l.p. by accident. I meant to post this
to Prothon-users.
Oh, no problem, there's some Python content (see below for some comments
on it)...
....
This isn't really a very clear description of what's going on in
Python. It won't matter to the Prothon users, but don't want any Python
users to get confused...

Looking up klass.func returns an unbound instance method, this is a
function wrapper which basically just says "hey, you're a member
function of a class, check to be sure that your first argument is a
member of that class". This is done by the function's descriptor
hooks which allow it to return a wrapped object when the user
attempts to retrieve the value from another object (such as a class
or an instance). So, in a sense, yes, the class cannot be the
target of that *particular* call, as the unbound method object you
retrieved will reject anything other than an instance of the class.

Bound instance methods are a similar wrapper, but they say
"curry/bind your first argument (normally self) to this value then
call the underlying function". They are created on object.method
access by the same function descriptor hooks.

The point of all that being that classes most definitely *can* be the
target of a call. Python's classes are first-class objects. In
particular, they are instances of metaclasses, and can have meta-methods
defined which take the class as their first parameter just like a normal
method-call.
.... def r( cls ):
.... return 42
.... .... __metaclass__ = k
....
There's very little "special" about classes other than that they have
some syntactic shortcuts for creating them and for looking up attributes
of their instances within them. Python isn't looking at every method
call and saying "hey, that's a class, that can't be the first parameter
to a function/method!", it (particularly the unbound instance object) is
saying "hey, you're not an instance of my class, go to heck" and never
thinks about whether the object is *particularly* a class or not.

Classes are special in Python, but not nearly as special as you might
think from a class-less perspective :) ,
Mike

By the way, the modern Python idiom is:

super( klass2, self ).func( )

but that wouldn't help in explaining the logic for the Prothon
choice, so no biggie :) .

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

Mark Hahn

Mike said:
This isn't really a very clear description of what's going on in
Python. It won't matter to the Prothon users, but don't want any
Python users to get confused...

By the way, the modern Python idiom is:

super( klass2, self ).func( )

You're kidding. That seems like a big leap backwards in friendliness. Kind
of a syntax castor oil.

That's explains why Joe Mason did his proposal for Prothon delegation using
that same idiom for Prothon. I thought he was somewhat crazy wanting us to
type all that each time.

What problem caused Python to want to switch to such a general operation?
What is the usage case that is so important that it is making eveyone wear
out their keyboards typing that monstrosity?

Oh well, I guess it gives me one more argument to pitch for Prothon...
 
E

Erik Max Francis

Mark said:
My inability to understand this stuff is what drove me to do Prothon
<grin>.
All the hidden wrapped this and wrapped that confused me to no end. ...
You're kidding. That seems like a big leap backwards in friendliness.
Kind
of a syntax castor oil.

Says the guy who's introducing a new operator to his language before
even understanding the behavior of the original one, by his own
admission ...
 
M

Mark Hahn

Erik Max Francis said:
Says the guy who's introducing a new operator to his language before
even understanding the behavior of the original one, by his own
admission ...

Well, I do tend to exaggerate a bit. I can understand it when I study it,
but in everyday coding it does not roll off my fingers. Also, it is
possible to design something new without understanding the old. It might
even be an advantage in some circumstances to not be tainted by old
concepts.

I am serious when I say I think that Python has headed off into egghead land
a bit and I feel that keeps a lot of people from switching to it. I think
that this heady stuff scares them off. I really am trying to make things
simpler in Prothon. Now, whether I can succeed or not is another question.
Only time will tell.
 
E

Erik Max Francis

Mark said:
Well, I do tend to exaggerate a bit. I can understand it when I study
it,
but in everyday coding it does not roll off my fingers. Also, it is
possible to design something new without understanding the old.

It is _possible_. But it is not a very good idea.
I am serious when I say I think that Python has headed off into
egghead land
a bit and I feel that keeps a lot of people from switching to it. I
think
that this heady stuff scares them off. I really am trying to make
things
simpler in Prothon. Now, whether I can succeed or not is another
question.
Only time will tell.

Other than the basic premise of Prothon, every single decision I've seen
you make (or consider) looks wholly stylistic, awkward or even arcane,
and the opposite of the one I, or I think Guido, would have chosen.
Being a fan of Io, I think prototype-languages are interesting. Even so
far, I lost interest in looking at the actual main feature of Prothon,
after seeing all the extra baggage that was brought on in unecessary
stylistic changes.

Seriously considering every single possible proposal is not
constructive. Without a strong sense of what the language should look
like, Prothon is going to continue to look more and more like Perl.
It's already most of the way there.
 
P

Peter Hansen

Mark said:
I am serious when I say I think that Python has headed off into egghead land
a bit and I feel that keeps a lot of people from switching to it. I think
that this heady stuff scares them off.

Not likely. Most people learning or using Python still have little
interest in or need for metaclass programming, and I *strongly*
doubt it has scared off more than a handful of people.

Likewise, the differences between prototype-based languages and
class-based languages do not appear significant enough to be
the sole reason to pick one over the other. The community,
on the other hand, and the libraries -- well, those are good
reasons for picking Python. It will be interesting to see whether
Prothon manages to achieve similar success in either area.
And if it does, well, see my first point in this sentence again...

-Peter
 
G

Greg Ewing

Mark said:
You're kidding. That seems like a big leap backwards in friendliness.

Don't worry, the traditional form of super call in Python
isn't going away any time soon. It's not replaced by this;
they do different things.

The new form is occasionally needed, but not very often.
I haven't found a use for it myself yet. (I *thought* I
had found one the other day, but it turned out I hadn't.)
 
M

Mark Hahn

Peter Hansen said:
It will be interesting to see whether
Prothon manages to achieve similar success in either area.

I apologize if I got competitive. As I have said many times, I don't
expect Prothon to compete with Python. It's hard to bust your butt on
something day in and out without getting carried away.
 
M

Mark Hahn

Seriously considering every single possible proposal is not constructive.

I could see one making an argument about efficiency, but to say it's not
constructive is ludicrous.
Without a strong sense of what the language should look
like, Prothon is going to continue to look more and more like Perl.
It's already most of the way there.

You haven't seen the final product. My design process is (and always has
been) to go through an expansion phase where more and more gets added or at
least considered and then through a contraction phase where the fat gets cut
out. I find this process works very well.

Please hold off your ad hominem attacks until the product is designed, thank
you very much.
 
B

Ben Finney

Erik Max Francis said:
Seriously considering every single possible proposal is not
constructive.
[...]
Without a strong sense of what the language should look
like, Prothon is going to continue to look more and more like Perl.
It's already most of the way there.

Please hold off your ad hominem attacks until the product is designed,
thank you very much.

Please understand what an ad hominem attack is before accusing others of
using it, thank you very much:

<http://www.infidels.org/news/atheism/logic.html#hominem>

Erik's assertions were relating to the topic, not to your person or
circumstances. They were not argumentum ad hominem.
 
M

Mike C. Fletcher

Mark said:
Mike C. Fletcher wrote:




My inability to understand this stuff is what drove me to do Prothon <grin>.
All the hidden wrapped this and wrapped that confused me to no end.
Fascinating. Most users never even notice this stuff, let alone getting
so worked up about it that they start a whole separate language ;) .
After all, they don't generally even know that metaclasses *exist* and
just know that it all works exactly as they would expect. You for
instance, were describing how the interpreter just knows that a class
can't be the target of an unbound class method. Sure, *maybe* it's all
a hideously complex mess that has people running screaming from Python
in horror, but from where I sit it is an extremely elegant system that
most people use without any impedance mismatch at all.
You're kidding. That seems like a big leap backwards in friendliness. Kind
of a syntax castor oil.
Explicit is better than implicit. You are attempting to call the
superclass' method; using:

klass.func( self )

is actually a far less maintainable and composable idiom. Here you are
saying "call this *particular* superclass' method", introducing a
dependency on the class' current superclass inside the method call. The
super() version does introduce a dependency on the *current* class
inside the call, but that's generally far less likely to mess up as code
gets revised.

super(), in other words, is a practical solution to avoiding the
explicit dependencies that crop up when you directly reference a
super-class. It solves problems *for large-systems developers* who need
robust, cooperative, composable functionality (e.g. via mix-in
classes). klass.func() might seem prettier and shorter in small
systems, but it's something that Python's user community has outgrown
over the years (if you can troll so can I ;) ).
That's explains why Joe Mason did his proposal for Prothon delegation using
that same idiom for Prothon. I thought he was somewhat crazy wanting us to
type all that each time.
It's not the most elegant spelling of the idiom, that's true, but it was
added without introducing any new magic. When creating a new language
you can decide to add new magic to the system solely as a question of
"what is right". When evolving a highly successful system, introducing
new magic is a serious concern:

super.func()

with super as a key-word would be fine in Prothon, as there's no code
that depends on using the name super.

super().func()

would work just as well, with the interpreter figuring out which class
super() is being called from within but what happens when it's defined
outside a class and injected later? After all, it's the class where it's
*defined* that matters, not the one where it's being used. So Guido
went for the minimum of magic. There's no special restriction on a
function that uses super that the function must be defined in a class,
there's no rules to figure out whether it affects inner or outer
classes, there's, in short, no magic required to learn the idiom, it's a
simple class instantiation like just about everything else.

Special cases aren't special enough to break the rules.
Although practicality beats purity.

super is used primarily by large-systems developers (meta-programmers),
so having the functionality require the introduction of special magic
and rules for regular users (every time they see an instance of "magic"
they need to learn what it does) seems unnecessarily "special".
Implementing super as a simple class means that, should someone be
interested, they can simply look up the implementation and go "ah, I see
what it does", but until then they can understand it as a simple call
that returns a wrapper which gives the superclass of the passed class in
the passed instance' mro... i.e. it's a black box that follows all the
regular rules of functions/callables in Python.

Language design is about balancing the minimal set of ideas needed to
give full generality and power with the need for expressivity and
practicality. So far Guido's decisions have been, IMO, a fairly good
balance. There are warts, but every language will have warts. Python
is a *small* language where, particularly in the later incarnations the
special cases are going away and the same basic mechanisms are getting
used in more and more places (e.g. with descriptors). The reduction of
special cases is an important design tool.
What problem caused Python to want to switch to such a general operation?
What is the usage case that is so important that it is making eveyone wear
out their keyboards typing that monstrosity?
Remember, this is the Python list, we tend to find hugely rhetorical
arguments somewhat off-putting ;) . On the other hand, we've
extinguished more potential flamewars than I can count over the years,
so it's not like the universe is going to collapse because of a few
overblown statements :) . If it did I would have doomed us all ages ago
:) .
Oh well, I guess it gives me one more argument to pitch for Prothon...
Sure, the magic you sprinkle through your system is part of its flavour
and character, that character is how languages sell themselves. Though
honestly, if someone seriously came up to me and said:

"Switch to Frobnaz, it has explicit syntax for referencing a
superclass rather than that archaic explicit invocation stuff in Python"

I'd probably dismiss them out of hand as being so totally out of touch
with reality as to be not worth the effort of listening (well, not
really, I *try* not to dismiss people out of hand no matter how crazy
they are). Addressing a few of Python's warts is *not* going to make
the world beat a path to your door. If you are going to get people to
make a clean leap to your language (i.e. it's not source-code compatible
with their current language, and doesn't have some compelling
feature/niche) you need to design something that's about two times
better, and you don't design something twice as good by copying and
tweaking. You do it by making intelligent design decisions that create
a coherent language that fits well with people's expectations, that fits
in their mind without a lot of magic and arbitrary rules to remember
(PERL, of course being the exception that proves the rule, where the
attempt is to simply guess everything the user might want to do and
create an explicit syntax for that ;) ).

Your language *will* have it's own warts, that's a simple reality,
pointing out that you don't have the same warts *in the same places* as
another language is not a compelling argument for switching. For
instance, I would almost certainly consider the fishHeight$Somewhere()
syntax to be a wart ;) , so being told that I can save 20 characters or
so in typing super (which I've only done maybe one or two hundred times
since it was introduced) by introducing something that my end-developers
are going to have to be trained on doesn't really make me wet my pants
in anticipation and joy :) . After all, I've probably typed almost that
much in this email alone.

Oops, dang keyboard wore out again ;) ,
Mike

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

Mark Hahn

Ben Finney said:
Please understand what an ad hominem attack is before accusing others of
using it, thank you very much:

What did I do? Prothon is accused of looking like Perl (which I mistakenly
took as an ad hominem slur, but now I see that he was serious) and I am
accused of not knowing the English language (even though I have degrees from
both Stanford University and Princeton University).

I guess I'll go back to the Prothon mailing lists with my tail between my
legs....
 
C

Carl Banks

Mark said:
What did I do? Prothon is accused of looking like Perl (which I mistakenly
took as an ad hominem slur,

Ok, I gotta admit, that's understandable.
 
M

Mark Hahn

Mike said:
Fascinating. Most users never even notice this stuff, let alone getting
so worked up about it that they start a whole separate language ;) .

Well, I do exaggerate a bit :)
super(), in other words, is a practical solution to avoiding the
explicit dependencies that crop up when you directly reference a
super-class.

Prothon also has a seperate super operator ( ^ ). ^var means to get the
first attrbute named var from a prototype of self instead of self itself.
It uses the ordered list of prototypes like Python does. So ^func() does
what you are referring to.

Internally in the interpreter I have the full Python super function almost
exactly. It's no coincidence. You need that to make inheritance work. I
can bring it out for the Prothon user, but I originally designed prothon
with keywords and symbols, not functions, something I'm taking a lot of heat
for now.
Sure, the magic you sprinkle through your system is part of its
flavour
and character, that character is how languages sell themselves.
Though honestly, if someone seriously came up to me and said:

"Switch to Frobnaz, it has explicit syntax for referencing a
superclass rather than that archaic explicit invocation stuff in
Python"

I'd probably dismiss them out of hand as being so totally out of touch
with reality as to be not worth the effort of listening (well, not
really, I *try* not to dismiss people out of hand no matter how crazy
they are). Addressing a few of Python's warts is *not* going to make
the world beat a path to your door.

You've stretched my "one more thing to pitch" statement to the extreme
statement of "switch to this because of this one thing". Of course one
isn't going to care about one thing.
Your language *will* have it's own warts, that's a simple reality,
pointing out that you don't have the same warts *in the same places*
as another language is not a compelling argument for switching. For
instance, I would almost certainly consider the fishHeight$Somewhere()
syntax to be a wart ;)

You may very well be right. I'm trying to get it to fit into an overall
scheme, but it may not work. By itself it definitely is a wart. Don't
forget that you are looking at it in the context of Python. It is being put
into a different language with different problems.

My biggest problem right now is stupid aesthetics. I have to decide where
to place Prothon on the continuum between lisp and perl. When I crossed the
line and added $ for self people screamed bloody murder that it looked like
Perl. Before when I had a period for self they thought it looked great. I
can't believe how much they care about something so silly.

Anyway, thanks very much for your input. I'm sorry if you wore out your
keyboard. Luckily the prices have really come down :)
 
M

Mike C. Fletcher

Mark said:
Mike C. Fletcher wrote:

....

Internally in the interpreter I have the full Python super function almost
exactly. It's no coincidence. You need that to make inheritance work. I
can bring it out for the Prothon user, but I originally designed prothon
with keywords and symbols, not functions, something I'm taking a lot of heat
for now.
Heat is a good way to bake ideas and remove impurities.
You've stretched my "one more thing to pitch" statement to the extreme
statement of "switch to this because of this one thing". Of course one
isn't going to care about one thing.
Well, as I said, if you're going to have fun trolling I get to have fun
trolling back ;) . Basically, I'm saying this particular detail is not
an argument worth making on its own. The argument is going to be "it's
a clean, simple, balanced and elegant syntax" and this level of detail
is just part of that picture. Artwork is judged as a whole, and one
might critique a particular facet if it's horrible, but perfection is
assumed otherwise.
You may very well be right.
Never happened before, why assume it'd start now :) .
My biggest problem right now is stupid aesthetics. I have to decide where
to place Prothon on the continuum between lisp and perl.
*poke* surely you see the humour that a Python user will derive from
that statement :) ;) .
When I crossed the
line and added $ for self people screamed bloody murder that it looked like
Perl. Before when I had a period for self they thought it looked great. I
can't believe how much they care about something so silly.
Comparatively, instance-attribute access is used three or four times a
minute when coding, while super is used once or twice a month for
non-framework-programmers, so yes, I can see someone screaming bloody
murder if they suddenly are looking at a screen full of $This and $that
variables. $ is basically a character as far as glyphs go, it's a
full-height glyph with ascenders and descenders, is very similar to a
capital S, and generally makes reading code much harder as it obscures
word-shape; .this or even self.this is much easier to read because you
can pick out the words using your learned vocabulary of word-shapes.

Readability counts

BTW, I'm a professional designer, so "stupid aesthetics" are what I care
about whenever I get a chance ;) .
Anyway, thanks very much for your input. I'm sorry if you wore out your
keyboard. Luckily the prices have really come down :)
Unfortunately, MS doesn't make the classic Natural Keyboard any more
(they just make that darned Natural Elite and the
egads-it's-covered-in-pointless-extra-buttons USB Natural), so I have to
savour every keystroke ;) .

That's why I never post to newsgroups,
Mike

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

Jeff Epler

My biggest problem right now is stupid aesthetics. I have to decide where
to place Prothon on the continuum between lisp and perl. When I crossed the
line and added $ for self people screamed bloody murder that it looked like
Perl. Before when I had a period for self they thought it looked great. I
can't believe how much they care about something so silly.

I didn't know about your ^ syntax either.

In Python, there is one way[*] to get an attribute on an object. This
works whether it's a data attribute on the instance, a data attribute on
the class or a superclass, an instancemethod, classmethod, or
staticmethod:

obj.attr

Having all of obj.attr, obj$attr and obj^attr *does* reek of perl's
$var, @var, %var distinction (which I have never bothered to
understand).

To me it looks like you've eliminated/combined one thing (instances +
classes become objects) but as a result you've had to invent two new
kinds of complication.

What may have made people jump to a conclusion about $ is that you wrote
something like "$ will remind users of $elf". This reeks of Perl's bad
explanations of why all their internal variables with punctuation names
are really mnemonic for something:
$/ The input record separator, newline by default.
(Mnemonic: / delimits line boundaries when quoting poetry.)
$. Current line number for the last filehandle accessed.
(Mnemonic: many programs use "." to mean the current line
number.)
Yeah, right.

Jeff
[*] Yes, I know full well there are other ways you can do it
getattr(obj, "attr"), obj.__dict__['attr'], etc, etc. My point is,
then, that everything can be done with a single "dotted name" syntax.
 
P

Peter Hansen

Mike said:
instance, I would almost certainly consider the fishHeight$Somewhere()

Mike, you haven't been keeping up with the other thread. I think the
decision is now:

fish_height$some_where()

;-) ;-)

-Peter
 
A

A.M. Kuchling

Being a fan of Io, I think prototype-languages are interesting. Even so
far, I lost interest in looking at the actual main feature of Prothon,
after seeing all the extra baggage that was brought on in unecessary
stylistic changes.

There's a rule in experiments that you should only change one thing at a
time, trying to answer a single question with each change. Prothon started
out asking two questions:

* Does implementing an interpreter on top of the Apache Portable Runtime
for the sake of free threading work? (Presumably the answer is yes, since
Prothon does run. I haven't seen performance numbers on Prothon, though.)
* Is prototyping a workable replacement for a class-based object system?
Unclear, since I don't know that anyone has written sizable systems
in Prothon yet.

The problem is that if you then make a whole bunch of additional changes --
a 'with' statement, changing the rules for indenting, changing the names of
various built-in methods -- it becomes harder for Python users to try out
the new language for a while because there are more changes they have to
cope with. After a certain point the number of crossover users dwindles to
near-zero. None of these changes is critical or results in a 100%
improvement in functionality (or even a 10% one), but their collective
effect is to make the distance too great to cross conveniently; you might as
well start a new language with a blank sheet of paper at that point.

--amk
 

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

No members online now.

Forum statistics

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

Latest Threads

Top