Python from Wise Guy's Viewpoint

T

Tomasz Zielonka

Kenny said:
Lisp consistently errs on the side of more expressive power. The idea of
putting on a strait jacket while coding to protect us from ourselves
just seems batty. Similarly, a recent ex-C++ journal editor recently
wrote that test-driven development now gives him the code QA peace of
mind he once sought from strong static typing.

C++ is not the best example of strong static typing. It is a language
full of traps, which can't be detected by its type system.
An admitted former static typing bigot, he finished by wondering
aloud, "Will we all be coding in Python ten years from now?"

kenny

Best regards,
Tom
 
S

Scott McIntire

Kenny Tilton said:
Lisp consistently errs on the side of more expressive power. The idea of
putting on a strait jacket while coding to protect us from ourselves
just seems batty. Similarly, a recent ex-C++ journal editor recently
wrote that test-driven development now gives him the code QA peace of
mind he once sought from strong static typing. An admitted former static
typing bigot, he finished by wondering aloud, "Will we all be coding in
Python ten years from now?"

kenny

There was a nice example from one of the ILC 2003 talks about a Europian
Space Agency rocket exploding with a valueable payload. My understanding was
that there was testing, but maybe too much emphasis was placed the static
type checking of the language used to control the rocket. The end result was
a run time arithmetic overflow which the code intepreted as "rocket off
course". The rocket code instructions in this event were to self destruct.
It seems to me that the Agency would have fared better if they just used
Lisp - which has bignums - and relied more on regression suites and less on
the belief that static type checking systems would save the day.

I'd be interested in hearing more about this from someone who knows the
details.

-R. Scott McIntire
 
A

Alex Martelli

Frode said:
John Thingstad said:
[..] Functions are internally delt with using dictionaies. The

Rather, _names_ are dealt that way (for globals; it's faster for
locals -- then, the compiler can turn the name into an index
into the table of locals' values), whether they're names of functions
or names of other values (Python doesn't separate those namespaces).
So to get from the ID to the bytecode, you go through a dictionary?

No; it's up to the implementation, but in CPython the id is the
memory address of the function object, so the bytecode's directly
accessed from there (well, there's a couple of indirectness --
function object to code object to code string -- nothing important).
And the mapping from name to ID happens perhaps when the caller is
bytecode-compiled?

No, it's a lookup. Dict lookup for globals, fast (index in table)
lookup for locals (making locals much faster to access), but a
lookup anyway. I've already posted about how psyco can optimize
this, being a specializing compiler, when it notices the dynamic
possibilities are not being used in a given case.


Alex
 
T

Terry Reedy

Scott McIntire said:
There was a nice example from one of the ILC 2003 talks about a Europian
Space Agency rocket exploding with a valueable payload. My understanding was
that there was testing, but maybe too much emphasis was placed the static
type checking of the language used to control the rocket. The end result was
a run time arithmetic overflow which the code intepreted as "rocket off
course". The rocket code instructions in this event were to self destruct.
It seems to me that the Agency would have fared better if they just used
Lisp - which has bignums - and relied more on regression suites and less on
the belief that static type checking systems would save the day.

I'd be interested in hearing more about this from someone who knows the
details.

I believe you are referring to the first flight of the Ariane 5
(sp?). The report of the investigating commission is on the web
somewhere and an interesting read. They identified about five
distinct errors. Try google.

Terry
 
D

Dennis Lee Bieber

Scott McIntire fed this fish to the penguins on Sunday 19 October 2003
15:39 pm:
There was a nice example from one of the ILC 2003 talks about a
Europian Space Agency rocket exploding with a valueable payload. My
understanding was that there was testing, but maybe too much emphasis
was placed the static type checking of the language used to control
the rocket. The end result was a run time arithmetic overflow which
the code intepreted as "rocket off course". The rocket code
instructions in this event were to self destruct. It seems to me that
the Agency would have fared better if they just used Lisp - which has
bignums - and relied more on regression suites and less on the belief
that static type checking systems would save the day.

I'd be interested in hearing more about this from someone who knows
the
details.
Just check the archives for comp.lang.ada and Ariane-5.

Short version: The software performed correctly, to specification
(including the failure mode) -- ON THE ARIANE 4 FOR WHICH IT WAS
DESIGNED.

The software was then dropped into the ARIANE 5 with NO REVIEW of
requirements. Two things were different -- the A-5 was capable of more
severe maneuvering, AND apparently the A-5 launch sequence did not need
this code to run for some 40 seconds after ignition (something about
the A-4 launch sequence allowed it to be aborted and restarted in the
40 second span, so the code had to keep up-to-date navigational fixes;
the A-5 OTOH is in space by that point, no post ignition holds).

On the A-4, any values that were that extreme were a sign of critical
malfunction and the software was to shutdown. Which is what it did on
the A-5. Of course, the backup computer then saw the same "malfunction"
and shut down too... For the A-4, you wouldn't WANT the computer to try
processing with those values that were so far out of performance specs
that the rocket had to be tumbling out of control anyways.

The bean-counters apparently did not allow the folks with the A-5
requirements to examine the A-4 code for compliance, and the A-4 Coders
obviously never knew about the A-5 performance specs.

LISP wouldn't have helped -- since the A-4 code was supposed to
failure with values that large... And would have done the same thing if
plugged in the A-5. (Or are you proposing that the A-4 code is supposed
to ignore a performance requirement?)



--
 
K

Kenny Tilton

Dennis said:
Scott McIntire fed this fish to the penguins on Sunday 19 October 2003
15:39 pm:



Just check the archives for comp.lang.ada and Ariane-5.

Short version: The software performed correctly, to specification
(including the failure mode) -- ON THE ARIANE 4 FOR WHICH IT WAS
DESIGNED.

Nonsense. From: http://www.sp.ph.ic.ac.uk/Cluster/report.html

"The internal SRI software exception was caused during execution of a
data conversion from 64-bit floating point to 16-bit signed integer
value. The floating point number which was converted had a value greater
than what could be represented by a 16-bit signed integer. This resulted
in an Operand Error. The data conversion instructions (in Ada code) were
not protected from causing an Operand Error, although other conversions
of comparable variables in the same place in the code were protected.
The error occurred in a part of the software that only performs
alignment of the strap-down inertial platform. This software module
computes meaningful results only before lift-off. As soon as the
launcher lifts off, this function serves no purpose."

LISP wouldn't have helped -- since the A-4 code was supposed to
failure with values that large... And would have done the same thing if
plugged in the A-5. (Or are you proposing that the A-4 code is supposed
to ignore a performance requirement?)

"supposed to" fail? chya. This was nothing more than an unhandled
exception crashing the sytem and its identical backup. Other conversions
were protected so they could handle things intelligently, this bad boy
went unguarded. Note also that the code functionality was pre-ignition
only, so there is no way they were thinking that a cool way to abort the
flight would be to leave a program exception unhandled.

What happened (aside from an unnecessary chunk of code running
increasing risk to no good end) is that the extra power of the A5 caused
oscillations greater than those seen in the A4. Those greater
oscillations took the 64-bit float beyond what would fit in the 16-bit
int. kablam. Operand Error. This is not a system saying "whoa, out of
range, abort".

As for Lisp not helping:
> most-positive-fixnum ;; constant provided by implementation 536870911

> (1+ most-positive-fixnum) ;; overflow fixnum type and... 536870912

> (type-of (1+ most-positive-fixnum)) ;; ...auto bignum type BIGNUM

> (round most-positive-single-float) ;; or floor or ceiling 340282346638528859811704183484516925440
0.0

> (type-of *)
BIGNUM

kenny
 
H

Hannu Kankaanp??

THE BAD:

1. f(x,y,z) sucks. f x y z would be much easier to type (see Haskell)
90% of the code is function applictions. Why not make it convenient?

Python has been designed to attract non-programmers as well. Don't
you think f(x,y,z) resembles the mathematical notation of passing
a function some parameters, instead of "f x y z"?
5. Why do you need "def" ? In Haskell, you'd write
square x = x * x

The reason is just to make it clearer that we're defining
a function. I wonder why you didn't complain about
the colons at the beginning of each block.. Some syntax is
there just to add readability. I suppose it means nothing
to you that Python is compared to executable pseudocode.
It means to Pythonistas.
6. Requiring "return" is also dumb (see #5)

You really don't get any of this "explicit is better than implicit"
thing, do you? Requiring people to write "return" instead of
leaving it as optional like in Ruby, is again one reason why
Pythonistas *like* Python instead of Ruby. You come to
a Python group (and cross-post this meaninglessly everywhere
even though it only concerns Pythonistas) claiming that the
features we like are dumb, and you wonder why people think
of you as a troll..

Anyway, as a conclusion, I believe you'd be much happier with
Ruby than with Python. It doesn't do this weird "statement vs
expression" business, it has optional return, it has optional
parens with function calls, and probably more of these things
"fixed" that you consider Python's downsides. You're trying to
make Python into a language that already exists, it seems, but
for some reason Pythonistas are happy with Python and not rapidly
converting to Ruby or Haskell. Instead of trying to tell us
what we like (and failing at that, as you can see), maybe you
should try to think for a while of why we like Python.

By the way, have you already posted a similar message
to comp.std.c++, saying what they should change about C++
to make it more like Haskell or Ruby? I'd love to read it
(it could be hilarious) ;)
 
F

Fergus Henderson

Kenny Tilton said:
Nonsense.

No, that is exactly right. Like the man said, read the archives for
comp.lang.ada.
From: http://www.sp.ph.ic.ac.uk/Cluster/report.html

"The internal SRI software exception was caused during execution of a
data conversion from 64-bit floating point to 16-bit signed integer
value. The floating point number which was converted had a value greater
than what could be represented by a 16-bit signed integer. This resulted
in an Operand Error. The data conversion instructions (in Ada code) were
not protected from causing an Operand Error, although other conversions
of comparable variables in the same place in the code were protected.
The error occurred in a part of the software that only performs
alignment of the strap-down inertial platform. This software module
computes meaningful results only before lift-off. As soon as the
launcher lifts off, this function serves no purpose."

That's all true, but it is only part of the story, and selectively quoting
just that part is misleading in this context.

For a more detailed answer, see
"supposed to" fail? chya. This was nothing more than an unhandled
exception crashing the sytem and its identical backup. Other conversions
were protected so they could handle things intelligently, this bad boy
went unguarded.

The reason that it went unguarded is that the programmers DELIBERATELY
omitted an exception handler for it. The post at the URL quoted above
explains why.
 
D

Duncan Booth

(e-mail address removed) wrote in
1. f(x,y,z) sucks. f x y z would be much easier to type (see Haskell)
90% of the code is function applictions. Why not make it convenient?

What syntax do you propose to use for f(x(y,z)), or f(x(y(z))), or
f(x,y(z)) or f(x(y),z) or f(x)(y)(z) or numerous other variants which are
not currently ambiguous?
 
A

Alex Martelli

Duncan said:
(e-mail address removed) wrote in


What syntax do you propose to use for f(x(y,z)), or f(x(y(z))), or
f(x,y(z)) or f(x(y),z) or f(x)(y)(z) or numerous other variants which are
not currently ambiguous?

Haskell has it easy -- f x y z is the same as ((f x) y) z -- as an
N-ary function is "conceptualized" as a unary function that returns
an (N-1)-ary function [as Haskell Curry conceptualized it -- which
is why the language is named Haskell, and the concept currying:)].
So, your 5th case, f(x)(y)(z), would be exactly the same thing.

When you want to apply operators in other than their normal order
of priority, then and only then you must use parentheses, e.g. for
your various cases they would be f (x y z) [1st case], f (x (y z))
[2nd case], f x (y z) [3rd case], f (x y) z [4th case]. You CAN,
if you wish, add redundant parentheses, of course, just like in
Python [where parentheses are overloaded to mean: function call,
class inheritance, function definition, empty tuples, tuples in
list comprehensions, apply operators with specified priority --
I hope I recalled them all;-)].

Of course this will never happen in Python, as it would break all
backwards compatibility. And I doubt it could sensibly happen in
any "simil-Python" without adopting many other Haskell ideas, such
as implicit currying and nonstrictness. What "x = f" should mean
in a language with assignment, everything first-class, and implicit
rather than explicit calling, is quite troublesome too.

Ruby allows some calls without parentheses, but the way it disambiguates
"f x y" between f(x(y)) and f(x, y) is, IMHO, pricey -- it has to KNOW
whether x is a method, and if it is it won't just let you pass it as such
as an argument to f; that's the slippery slope whereby you end up having to
write x.call(y) because not just any object is callable.
"x = f" CALLS f if f is a method, so you can't just treat methods
as first-class citizens like any other... etc, etc...
AND good Ruby texts recommend AVOIDING "f x y" without parentheses,
anyway, because it's ambiguous to a human reader, even when it's
clear to the compiler -- so the benefit you get for that price is
dubious indeed.


Alex
 
A

Alex Martelli

Hannu said:
(e-mail address removed) wrote in message


Python has been designed to attract non-programmers as well. Don't
you think f(x,y,z) resembles the mathematical notation of passing
a function some parameters, instead of "f x y z"?

Yes -- which is exactly why many non-programmers would prefer the
parentheses-less notation -- with more obvious names of course;-).
E.g.:
emitwarning URGENT "meltdown imminent!!!"
DOES look nicer to non-programmers than
emitwarning(URGENT, "meltdown imminent!!!")

Indeed, such languages as Visual Basic and Ruby do allow calling
without parentheses, no doubt because of this "nice look" thing.

However, as I explained elsewhere, there are probably-insuperable
language-design problems in merging "implicit call" and first-classness
of all names unless you basically go all the way following Haskell
with implicit currying and non-strictness (and assignments should
probably go away too, else how to distinguish between assigning to
x a nullary function f itself, and assigning to x the result of
_calling_ f without arguments...?). Not to mention:

emitwarning URGENT highlight "meltdown imminent!!!"

where the need to disambiguate between highlight being the second
of three parameters to emitwarning, or a function called with
the string as its sole parameter and its RESULT being the second
of two parameters to emitwarning, is important for human readers
(indeed some languages that DO allow parentheses-less calls, such
as Ruby, warn against actually USING this possibility in all cases
where ambiguity-to-human-readers may result, such as the above --
the need to be very careful and selective in actually using the
capability makes me less and less willing to pay any large price
for it).

In other words, it's a language design tradeoff, like so many
others -- one which I believe both Python and Haskell got just
right for their different audiences and semantics (I know VB
_didn't_, and I suspend judgment on Ruby -- maybe firstclassness
of all names isn't as important as it FEELS to me, but...).

You really don't get any of this "explicit is better than implicit"
thing, do you? Requiring people to write "return" instead of
leaving it as optional like in Ruby, is again one reason why
Pythonistas *like* Python instead of Ruby. You come to

I think that making return optional is slightly error-prone,
but it DOES make the language easier to learn for newbies --
newbies often err, in Python, by writing such code as
def double(x): x+x
which indicates the lack of 'return' IS more natural than its
mandatory presence. So, it's a tradeoff one could sensibly
chose either way. Of course, such cases as:
def buhandclose(boh):
try: boh.buh()
finally: boh.close()
would give you a bad headache in trying to explain them to
newbies ("hmyes the result of buhandclose IS that of the
last expression it evaluates, BUT the one in the finally
clause, although evaluated AFTER boh.buh(), doesn't really
count because..." [keeps handwaving copiously & strenously]).
So, mandatory 'return' does make the language more uniform,
consistent, and easy to master, though not quite as easy to
"pick up casually in a semi-cooked manner". Still, I for
one don't condemn Ruby for making the opposite choice -- it
IS a nicely balanced issue, IMHO.

Anyway, as a conclusion, I believe you'd be much happier with
Ruby than with Python. It doesn't do this weird "statement vs
expression" business, it has optional return, it has optional
parens with function calls, and probably more of these things
"fixed" that you consider Python's downsides. You're trying to

But doesn't make higher-order-functions as much of a no-brainer
as they're in Python, sigh.
make Python into a language that already exists, it seems, but
for some reason Pythonistas are happy with Python and not rapidly
converting to Ruby or Haskell. Instead of trying to tell us

My own reasons for the choice of Python over Ruby are quite
nuanced and complicated, actually (those for either of them
over Haskell have much to do with pragmatism over purity:).

It boils down to my desire to write application programs,
often requiring cooperation of middling-sized groups of people,
rather than experimental frameworks, or programs written by a
lone coder or a small group of highly-attuned experts. I have
the highest respect for Ruby -- it just doesn't match my needs
QUITE as well as Python does. But, yes, if somebody doesn't
really think about what kind of programs they want to write,
but rather focuses on syntax sugar issues such as return being
optional or mandatory "per se", then it's definitely worthwhile
for that somebody to try Ruby and leave c.l.py in peace:).


Alex
 
G

Gerrit Holl

Hannu said:
Anyway, as a conclusion, I believe you'd be much happier with
Ruby than with Python. It doesn't do this weird "statement vs
expression" business, it has optional return, it has optional
parens with function calls, and probably more of these things
"fixed" that you consider Python's downsides. You're trying to
make Python into a language that already exists, it seems, but
for some reason Pythonistas are happy with Python and not rapidly
converting to Ruby or Haskell.

I wonder to what extent this statement is true. I know at least
1 Ruby programmer who came from Python, but this spot check should
not be trusted, since I know only 1 Ruby programmer and only 1
former Python programmer <g>. But I have heard that there are a
lot of former Python programmers in the Ruby community. I think
it is safe to say that of all languages Python programmers migrate
to, Ruby is the strongest magnet. OTOH, the migration of this part
of the Python community to Ruby may have been completed already,
of course.

Gerrit.

--
53. If any one be too lazy to keep his dam in proper condition, and
does not so keep it; if then the dam break and all the fields be flooded,
then shall he in whose dam the break occurred be sold for money, and the
money shall replace the corn which he has caused to be ruined.
-- 1780 BC, Hammurabi, Code of Law
 
J

Joachim Durchholz

Marcin said:
This doesn't matter until you provide an equally powerful mechanism which
fixes that. Which is it?

I don't think there is a satisfactory one. It's a fundamental problem:
if two people who don't know of each other can extend the same thing
(framework, base class, whatever) in different directions, who's
responsible for writing the code needed to combine these extensions?

Solutions that I have seen or thought about are:

1. Let the system decide. Technically feasible for base classes (in the
form of priorisation rules for multimethods), technically infeasible for
frameworks. The problem here is that the system doesn't (usually) have
enough information to reliably make the correct decision.

2. Let the system declare an error if the glue code isn't there.
Effectively prohibits all forms of dynamic code loading. Can create
risks in project management (unexpected error messages during code
integration near a project deadline - yuck). Creates a temptation to
hack the glue code up, by people who don't know the details of the two
modules involved.

3. Disallow extending in multiple directions. In other words, no
multimethods, and live with the asymmetry.
Too restricted to be comfortable with.

4. As (3), but allow multiple extensions if they are contained within
the same module. I.e. allow multiple dispatch within an "arithmetics"
module that defines the classes Integer, Real, Complex, etc. etc., but
don't allow additional multiple dispatch outside the module. (Single
dispatch would, of course, be OK.)

5. As (3), but require manual intervention. IOW let the two authors who
did the orthogonal extensions know about each other, and have each
module refer to the other, and each module carry the glue code required
to combine with the other.
Actually, this is the practice for various open source projects. For
example, authors of MTAs, mail servers etc. cooperate to set standards.
Of course, if the authors aren't interested in cooperating, this doesn't
work well either.

6. Don't use dynamic dispatch, use parametric polymorphism (or whatever
your language offers for that purpose, be it "generics" or "templates").

Regards,
Jo
 
J

Joachim Durchholz

Pascal said:
Do they suck more or less than the Visitor pattern?

Well, the visitor pattern is worse.
Generics would be better though.
So how do you implement an equality operator correctly with only single
dynamic dispatch?

Good question.

In practice, you don't use dispatch, you use some built-in mechanism.

Even more in practice, all equality operators that I have seen tended to
compare more or less than one wanted to have compared, at least for
complicated types with large hidden internal structures, or different
equivalent internal structures. I have seen many cases where people
implemented several equality operators - of course, with different
names, and for most cases, I'm under the impression they weren't even
aware that it was equality that they were implementing :)

Examples are:
Lisp with its multitude of equality predicates nicely exposes the
problems, and provides a solution.
Various string representations (7-bit Ascii, 8-bit Ascii, various
Unicode flavors). Do you want to compare representations or contents? Do
you need a code table to compare?
Various number representation: do you want to make 1 different from 1.0,
or do you want to have them equal?

I think that dynamic dispatch is an interesting answer, but not to
equality :)

Regards,
Jo
 
J

Joachim Durchholz

Kenny said:
Nonsense. From: http://www.sp.ph.ic.ac.uk/Cluster/report.html

"The internal SRI software exception was caused during execution of a
data conversion from 64-bit floating point to 16-bit signed integer
value. The floating point number which was converted had a value greater
than what could be represented by a 16-bit signed integer. This resulted
in an Operand Error. The data conversion instructions (in Ada code) were
not protected from causing an Operand Error, although other conversions
of comparable variables in the same place in the code were protected.
The error occurred in a part of the software that only performs
alignment of the strap-down inertial platform. This software module
computes meaningful results only before lift-off. As soon as the
launcher lifts off, this function serves no purpose."

That's the sequence of events that led to the crash.
Why this sequence could happen though it shouldn't have happened is
exactly how Dennis wrote it: the conversion caused an exception because
the Ariane-5 had a tilt angle beyond what the SRI was designed for.
What happened (aside from an unnecessary chunk of code running
increasing risk to no good end) is that the extra power of the A5 caused
oscillations greater than those seen in the A4. Those greater
oscillations took the 64-bit float beyond what would fit in the 16-bit
int. kablam. Operand Error. This is not a system saying "whoa, out of
range, abort".

As for Lisp not helping:

BIGNUM

Lisp might not have helped even in that case.
1. The SRI was designed for an angle that would have fit into a 16-bit
operand. If the exception hadn't been thrown, some hardware might still
have malfunctioned.
2. I'm pretty sure there's a reason (other than saving space) for that
conversion to 16 bits. I suspect it was to be fed into some hardware
register... in which case all bignums of the world aren't going to help.

Ariane 5 is mostly a lesson in management errors. Software methodology
might have helped, but just replacing the programming language would
have been insufficient (as usual - languages can make proper testing
easier or harder, but the trade-off will always be present).

Regards,
Jo
 
M

Marcin 'Qrczak' Kowalczyk

Followup-To: comp.lang.misc

I don't think there is a satisfactory one. It's a fundamental problem:
if two people who don't know of each other can extend the same thing
(framework, base class, whatever) in different directions, who's
responsible for writing the code needed to combine these extensions?

Indeed. I wouldn't thus blame the language mechanism.
1. Let the system decide. Technically feasible for base classes (in the
form of priorisation rules for multimethods), technically infeasible for
frameworks. The problem here is that the system doesn't (usually) have
enough information to reliably make the correct decision.

Sometimes the programmer can write enough default specializations that it
can be freely extended. Example: drawing shapes on devices. If every shape
is convertible to Bezier curves, and every device is capable of drawing
Bezier curves, then the most generic specialization, for arbitrary shape
and arbitrary device, will call 'draw' again with the shape converted to
Bezier curves.

The potential of multimethods is used: particular shapes have specialized
implementations for particular devices (drawing text is usually better
done more directly than through curves), separate modules can provide
additional shapes and additional devices. Yet it is safe and modular, as
long as people agree who provides a particular specialization.

It's easy to agree with a certain restriction: the specialization is
provided either by the module providing the shape or by module providing
the device. In practice the restriction doesn't have to be always followed
- it's enough that the module providing the specialization is known to all
people who might want to write their own, so I wouldn't advocate enforcing
the restriction on the language level.

I would favor multimethods even if they provided only solutions extensible
in one dimension, since they are nicer than having to enumerate all cases
in one place. Better to have a partially extensible mechanism than nothing.
Here it is extensible.
2. Let the system declare an error if the glue code isn't there.
Effectively prohibits all forms of dynamic code loading. Can create risks
in project management (unexpected error messages during code integration
near a project deadline - yuck). Creates a temptation to hack the glue
code up, by people who don't know the details of the two modules involved.

It would be interesting to let the system find the coverage of multimethods,
but without making it an error if not all combinations are covered. It's
useful to be able to test an incomplete program.

There is no definite answer for what kind of errors should prevent running
the program. It's similar to static/dynamic typing, or being able to
compile calls to unimplemented functions or not.

Even if the system shows that all combinations are covered, it doesn't
imply that they do the right thing. It's analogous to failing to override
a method in class-based OOP - the system doesn't know if the superclass
implementation is appropriate for the subclass. So you can't completely
rely on detection of such errors anyway.
3. Disallow extending in multiple directions. In other words, no
multimethods, and live with the asymmetry. Too restricted to be
comfortable with.

I agree.
4. As (3), but allow multiple extensions if they are contained within the
same module. I.e. allow multiple dispatch within an "arithmetics" module
that defines the classes Integer, Real, Complex, etc. etc., but don't
allow additional multiple dispatch outside the module. (Single dispatch
would, of course, be OK.)

For me it's still too restricted. It's a useful guideline to follow but
it should not be a hard requirement.
5. As (3), but require manual intervention. IOW let the two authors who
did the orthogonal extensions know about each other, and have each module
refer to the other, and each module carry the glue code required to
combine with the other.

The glue code might reside in yet another module, especially if each of
the modules makes sense without the other (so it might better not depend
on it). Again, for me it's just a guideline - if one of the modules can
ensure that it's composable with the other, it's a good idea to change it -
but I would like to be able to provide the glue code elsewhere to make
them working in my program which uses both, and remove it once the modules
include the glue code themselves.
Actually, this is the practice for various open source projects. For
example, authors of MTAs, mail servers etc. cooperate to set standards. Of
course, if the authors aren't interested in cooperating, this doesn't work
well either.

The modules might also be a part of one program, where it's relatively
easy to make them cooperate. Inability to cope with some uses is generally
not a sufficient reason to reject a language mechamism which also has well
working uses.
6. Don't use dynamic dispatch, use parametric polymorphism (or whatever
your language offers for that purpose, be it "generics" or "templates").

I think it can rarely solve the same problem. C++ templates (which can
use overloaded operations, i.e. with implementation dependent on type
parameters) help only in statically resolvable cases. Fully parametric
polymorphism doesn't seem to help at all even in these cases (equality,
arithmetic).
 
P

Peter Hansen

Gerrit said:
But I have heard that there are a
lot of former Python programmers in the Ruby community. I think
it is safe to say that of all languages Python programmers migrate
to, Ruby is the strongest magnet. OTOH, the migration of this part
of the Python community to Ruby may have been completed already,
of course.

And also on the other hand, perhaps not enough time has yet passed for
us to see the migration of these fickle people *back* to Python. :)

-Peter
 
W

Wojtek Walczak

Dnia Sun, 19 Oct 2003 04:18:31 -0700 (PDT), (e-mail address removed) napisa³(a):
THE GOOD: [...]
THE BAD:
[...]

Well, in the variety of languages and plenty of conceptions you can search
for your language of choice. Because all the things you mentioned in
"THE BAD" are available in other languages it doesn't mean it should also
exist in Python. Languages are different, just as people are. If you find
Python has more cons than pros it means that this is not a language from
which you can take 100% of fun. Anyway, changing it into next haskell,
smalltalk or ruby has no sense. Python fills certain niche and it does
its job as it should. Differences are necessity, so don't waste your time
on talks about making Python similar to something else.
 
A

Alex Martelli

Pascal Costanza wrote:
...
So how do you implement an equality operator correctly with only single
dynamic dispatch?

Equality is easy, as it's commutative -- pseudocode for it might be:

def operator==(a, b):
try: return a.__eq__(b)
except I_Have_No_Idea:
try: return b.__eq__(a)
except I_Have_No_Idea:
return False

Non-commutative operators require a tad more, e.g. Python lets each
type define both an __add__ and a __radd__ (rightwise-add):

def operator+(a, b):
try: return a.__add__(b)
except (I_Have_No_Idea, AttributeError):
try: return b.__radd__(a)
except (I_Have_No_Idea, AttributeError):
raise TypeError, "can't add %r and %r" % (type(a),type(b))

Multimethods really shine in HARDER problems, e.g., when you have
MORE than just two operands (or, perhaps, some _very_ complicated
inheritance structure -- but in such cases, even multimethods are
admittedly no panacea). Python's pow(a, b, c) is an example --
and, indeed, Python does NOT let you overload THAT (3-operand)
version, only the two-operand one that you can spell pow(a, b)
or a**b.


ALex
 
M

Markus Mottl


Dennis is right: it was indeed a specification problem. AFAIK, the coder
had actually even proved formally that the exception could not arise
with the spec of Ariana 4. Lisp code, too, can suddenly raise unexpected
exceptions. The default behaviour of the system was to abort the mission
for safety reasons by blasting the rocket. This wasn't justified in this
case, but one is always more clever after the event...
"supposed to" fail? chya.

Indeed. Values this extreme were considered impossible on Ariane 4 and
taken as indication of such a serious failure that it would justify
aborting the mission.
This was nothing more than an unhandled exception crashing the sytem
and its identical backup.

Depends on what you mean by "crash": it certainly didn't segfault. It
just realized that something happened that wasn't supposed to happen
and reacted AS REQUIRED.
Other conversions were protected so they could handle things
intelligently, this bad boy went unguarded.

Bad, indeed, but absolutely safe with regard to the spec of Ariane 4.
Note also that the code functionality was pre-ignition
only, so there is no way they were thinking that a cool way to abort the
flight would be to leave a program exception unhandled.

This is a serious design error, not a problem of the programming language.
What happened (aside from an unnecessary chunk of code running
increasing risk to no good end)

Again, it's a design error.
is that the extra power of the A5 caused
oscillations greater than those seen in the A4. Those greater
oscillations took the 64-bit float beyond what would fit in the 16-bit
int. kablam. Operand Error. This is not a system saying "whoa, out of
range, abort".

Well, the system was indeed programmed to say "whoa, out of range, abort".
A design error.
As for Lisp not helping:

There is basically no difference between checking the type of a value
dynamically for validity and catching exceptions that get raised on
violations of certain constraints. One can forget to do both or react
to those events in a stupid way (or prove in both cases that the check /
exception handling is unnecessary given the spec).

Note that I am not defending ADA in any way or arguing against FPLs: in
fact, being an FPL-advocate myself I do think that FPLs (including Lisp)
have an edge what concerns writing safe code. But the Ariane-example just
doesn't support this claim. It was an absolutely horrible management
mistake to not check old code for compliance with the new spec. End
of story...

Regards,
Markus Mottl
 

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,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top