Could Python supplant Java?
James J. Besemer
jb at cascade-sys.com
Mon Aug 26 21:52:46 EDT 2002
Paul Foley wrote:
>On Fri, 23 Aug 2002 10:14:08 -0700, James J Besemer wrote:
>
>>Just Plain Wrong, certainly depends on what you're used to.
>>
>You mean if you're used to languages that do the wrong thing, you
>probably don't notice that it's wrong? Doesn't make it any less
>wrong, though.
>
I meant it in the exact same same vein that Pythonistas say all the time
about Python -- work around what you perceive to be a problem or
limitation and after a while you'll get used to it and come to accept
that it's not a problem. I can see how the way C++ works in this case
would be confusing for some, especially newbies, but it ceases to be a
problem after you learn the language.
>No, that's completely irrelevant. Casting, automatic or otherwise,
>really has nothing to do with it.
>
>If you used "virtual" it would work, regardless of any casts.
>
>You obviously didn't try it. It won't do what you say it will.
>
You're right. I was wrong about this, as I acknowledged earlier.
I actually did try it but I did the harder example first and forgot to
remove 'virtual' for the simpler case.
FWIW, I blame this and other careless errors on the fact that I had been
up for about 24 hours straight at the time.
>consider the possibility that if you
>knew it better, you might think it was more "Wrong".
>
Anything is possible but I don't think so.
For it to work the way you expect requires a late binding model -- a
table lookup for each access because nothing can be relied upon at
compile time. This is inconsistent with the whole design philosophy of
C++, which fixes all name and type bindings at compile time.
For better or worse, the truly innovative thing about C++ to be that it
offers most of the flexibility of other OOP languages (Polymorphism for
example) while still providing a strong compile time type checking and
binding of all symbolic references at link time. That is OOP without
the traditional runtime penalty. Now maybe Stroustrup was barking up
the wrong tree all the time striving to maintain these objectives (no GC
either) but it's an certainly important accomplishment in the history of
programming languages. Borland's Delphi made similar strategic design
decisions, so maybe it's not totally crazy.
The trade off is that your OOP application can run at machine speeds
without all the considerable overhead doing dictionary hash table
lookups for each name reference.
The difference is dramatic:
http://cascade-sys.com/~jb/Pythonetics/callcost/index.htm
The 100X or 200X runtime penalty clearly illustrates the difference
between early and late binding, IMO.
Now, whether the cost of the extra declarative burden (not to mention
the other complexities of C++) are worth the runtime savings depends on
your application. In many cases it is a loss because it takes more
programmer time ,which (in most cases) is way more valuable than
computer time. But sometimes the performance is worth the cost. It's
good to have the choice and it's good that you don't have to abandon OOP
to reap the benefits.
>>Clearly we disagree on the definition of Polymorphism. I think most authorities
>>agree that C++ has Polymorphism as demonstrated above.
>>
>C++ does have polymorphism, noone's denying that. But what you
>demonstrated above is not it. To get polymorphism in C++, you use
>"virtual".
>
Clearly we disagree and maybe we never will agree.
I've cited public 3rd party definitions previously and you've ignored
them. Here's SEVERAL MORE that support my broader view of Polymorphism
(which expressly includes operator overloading).
http://whatis.techtarget.com/definition/0,,sid9_gci212803,00.html
http://www.cyberdyne-object-sys.com/oofaq/oo-faq-S-2.1.0.5.html
http://www.javaworld.com/javaworld/jw-04-2001/jw-0413-polymorph.html
http://www.ida.his.se/ida/~jonas/ComponentSoftwareCourse/ch6-team2.pdf
Now to be sure, within the context of specific languages and
environments, I have seen narrower definitions of the term. But in
these cases they're defining how Polymorphism works in that particular
language or environment, where there's no point in discussing the more
general forms which do not exist.
I think we actually pretty much agree on how this all works. It's just
the definitions of terms where we differ. Just accept that Polymorphism
can be done in as static fashion and that it does not necessarily
involve objects (as my many sources above indicate) and we won't have an
argument.
>>The latter reference points out that C++ provides genuine Polymorphism without
>>using objects at all:
>>
>> int IsaT1( T1 a ){ return 1; }
>> int IsaT1( T2 b ){ return 0; }
>>
>>IsaT1( x ); // returns 0 or 1 depending on arg type
>>
>
>Only it /doesn't/ depend on the arg type. It depends on the static
>declarations. That's not the same thing.
>
The result from "IsaT1( x)" DOES very much "depend on arg type."
There's no other way to say it or think of it. The trick is that the
language is designed so that the compiler knows at compile time what the
object type always will be. Think of it as an optimization, where a
runtime symbol table lookup is replaced by a direct call to the proper
function.
OOP with zero runtime overhead -- this is a FEATURE not a gimmick.
>Try this:
>
> class A {};
> class B : public A {};
> class C : public A {};
>
> int isaB(A x) {return 0;}
> int isaB(B x) {return 1;}
>
> int buggy(A x) {return isaB(x);}
>
>now create a B instance and C instance and try calling isaB() on
>them. That works OK. Call buggy() on them. That fails.
>
It doesn't "fail". It merely does not do what YOU want it to do.
Buggy() by definition only works on objects of type A. In all calls to
buggy C++ coerces sub-types of A to type A. Since x can never be
anything but type A, the test can never be true. A global optimizing
compiler would convert it to "return 0".
Again, this is a feature.
I can see how, if the bulk of your OOP experience was with a late
binding language like Lisp, then this behavior would seem foreign. But
for those of us who's background is primarily with early binding
languages, it makes sense.
In this case, right or wrong is very much a relative term and depends on
your background and perspective.
>Feel free to rewrite it with pointers, if you still believe that will
>help. It won't. [And you can't even fix that with "virtual"]
>
You are right that virtual does not apply. However, there is nothing to
"fix". Function overloading is a form of Polymorphism that does not
involve Objects. Perfectly legitimate per the various 3rd party
authorities above.
>That's the difference between C++ overloading and proper multiple
>dispatch, as in Lisp. Overloading is just a syntactic hack [...]
>no different than writing [...]
>different names for each overloaded definition.
>
Partly true (in the case of regular functions) except the user doesn't
have to make up the goofy names. This is a significant feature.
However, overloading also applies to operators such as + and *. In this
case there is NO WAY to make up different names and get the same effect.
It's Polymorphism in it's basic form -- the same method works
differently when applied to objects of different types.
The operators emphasizes why this aspect of C++ OOP is an extension over
Python. In C++ you can define + and * for vectors and also a version
with scalar arguments. No way to do that with Python. Optional
arguments gives you a small subset of that capability but falls flat for
some other applications.
OOP doesn't always have to be implemented the way YOU happen to be used
to. It doesn't have to be a runtime phenomenon to be legitimate, let
alone useful.
How is "proper multiple dispatch" any better?
>>In Python you're hosed as there is no way to
>>discriminate class functions by argument signature. I hope that eventually changes.
>>
>I hope it doesn't. At least, not unless it changes toward multiple
>dispatch (which is unlikely).
>
Independently of implementation, I am describing a missing feature that
I think it would be very nice to have.
Python being a late binding language, it probably would do the final
function selection at runtime just like in LISP. How would that differ
from 'multiple dispatch'?
>Yes. Just like Python's dict. [In fact, if you have a quick look at
>the Python source code, you'll find that most of the built-in
>functions are in fact implemented by having pointers at fixed
>locations in the C struct that represents the class, too!]
>
I did not know that.
Then I would then say Python is using "early binding" for the built-ins.
;o)
And that it's smart and shows the value of early binding. ;o)
I mean, this case is completely different from C++'s virtual functions,
right? There's no decision at runtime based on object type, right? Just
a static table in partial recognition of the sometimes intolerable cost
of looking up each name at runtime.
>It's important that you use the same definitions as
>everybody else, not just make up your own as you're doing here.
>
That might be a fair criticism EXCEPT for the fact that *I* defined my
terms last week at the start of this branch of the discussion. If you
want to go back and argue the original definitions, that's one thing.
But you're out of line to accuse ME of being arbitrary when I clearly
defined the terms up front.
Clearly you're one of those zealots who believes that "late binding" is
an essential ingredient in Polymorphism and in OOP generally. I
disagree and think I've made my point. "We'll let the viewers decide."
In any case I am too exhausted with the subject to continue (unless
something REALLY juicy comes up).
However, I would like to hear more about why multiple dispatch is so
special.
You and I have had civil exchanges in the past. I hope we can agree to
disagree in this case without anybody getting their nose bent out of joint.
Regards
--jb
--
James J. Besemer 503-280-0838 voice
2727 NE Skidmore St. 503-280-0375 fax
Portland, Oregon 97211-6557 mailto:jb at cascade-sys.com
http://cascade-sys.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20020826/8e2c231e/attachment.html>
More information about the Python-list
mailing list