Python 1.6 The balanced language

Alex Martelli aleaxit at yahoo.com
Tue Sep 5 16:19:35 EDT 2000


"Manuel Gutierrez Algaba" <thor at localhost.localdomain> wrote in message
news:slrn8rae8k.atn.thor at localhost.localdomain...
> On Tue, 5  Alex Martelli <aleaxit at yahoo.com> wrote:
> >"Manuel Gutierrez Algaba" < wrote in message
> >news:slrn8r8cla.hrg.thor at localhost.localdomain...
> >    [snip]
> >> So types go against "functional".
> >
> >Most functional languages have (good) typesystems -- Haskell's being
> >definitely worth studying,
>
> I have the doc printed, ready to be studied, but Haskell syntax
> is almost as complex as Python 3000 syntax, so it's in the

Complex?  The *syntax* of Haskell?!  Why, it even uses
indent and linebreak Pythonically...


> >To continue your pipes/fluids analogy: not all fluids are safe to
> >run in every kind of pipe.  A language with types basically *lets*
> >you state that (some *make* you state that, but "good" typesystem
> >implies some measure of type-inferencing, by definition of 'good':-).
>
> A type is a way to prevent fluids to go thru wrong pipes. But,
> the question is what happens when we are preventing it all the time.
> We have building extremely limited functions , very robust,...
> but not so robust if you have to write several versions of
> the same function for processing different types .

So a language with a decent typesystem lets you do polymorphic
and 'generic' stuff, obviously.  Look at a Java dialect that adds just
a *little* bit of a good type system -- Hindley/Milner, like ML or
Haskell, and a little pattern-matching; it's called 'Pizza', and
although it's no longer maintained you can still have a look
at http://www.cis.unisa.edu.au/~pizza/ -- and, I think, download
and try out their compiler (the same group currently develops
'GJ', 'Generic Java', a perhaps more modest system that's maybe
due for incorporation in some future version of Java itself).

Just one little example...:

class Tree<A> implements Set<A> {
    case Empty;
    case Branch(A elem, Tree<A> left, Tree<A> right);
}

which as you see has Java-ish syntax (with the obvious <A>
annotations for parametric types), but semantics close to:

data Tree a = Empty
            | Branch (elem :: a, left, right :: Tree a)


With just a touch of this 'genericity', you mostly stop having to
"write several versions of the same function".


Dynamic typing has its place (or I wouldn't be such a
Python fan!-), but I suggest you don't knock static typing
until you've tried a _good_ implementation (ideally, a
Hindley/Milner typesystem).  Understanding the _true_
pluses and minuses of various typing styles will in any
case make you a better designer and coder even in just
one language, whatever its typesystem (or lack thereof,
if you ever find yourself faced with BCPL:-) happens to
be -- much like, say, being familiar with different structured
programming systems (if/while, etc) makes one a better
programmer even in bare machine code.


> At the end , you get lot of particular things, of particular
> redirections for determined fluids. It's better to have general
> treatments for general functionality. If I focus my effort in

It's best for everything to be as general as possible, but
not more general than that -- if you'll pardon the Einstein
paraphrase.

> general functionality what I'm doing is focusing in functionality.
> If I focus my effort in types, what I'm doing is low form
> of prerrequisites for every function, wasting the possibilities
> some functions may provide. If I think in terms of types, It's
> harder to think in terms of general functionality if we're focusing
> all the time of particular fluids.

Nope: typeclasses of fluid materials -- Noncorrosive, for example.

You do have the notion of typeclasses in Python: "a sequence",
for example, or "a file-like object"; you just lack the way to
*EXPRESS* this notion simply, directly, and explicitly _in the
language itself_.  So you express it in docs & comments, but
those are often not as precise as one would wish (and as an
expression in a formal language might make things): when
somebody says 'you pass a file-like object', what methods are
going to be called on it -- write? read? writelines? readlines?
close?  _Good_ docs would say that -- but why not have a
way to say it in the language itself?

To take a concrete example -- it's been true "since ages" in
Python that the for-statement:
    for item in foo:
        # whatever
accepts any 'sequencelike' foo -- it specifically requires foo
to have a __getitem__ that is called with an integer, from 0
upwards, and to have __getitem__ raise IndexError when
an item with a too-high index is first requested.  Further,
this specific protocol also applies to built-in functions such
as min and max; and to infix-operator in (unless, in the
most recent version, foo specifically implements another
special method, which is called just for that case).

These requirements, AFAIK, are _still_ nowhere to be
found in the docs that are distributed with Python -- I
hope I'm wrong regarding the latest doc release, but it
sure was not clearly documented there last time I had
to check, a few months ago.  Fortunately, this newsgroup
remedied this (and keeps remedying it as other people
have the same need to know).  But who will supply the
equivalent information for libraries that are nowhere as
popular or well-documented as the Python language and
its builtin libraries...?

Now THIS is 'wasting the possibilities some functions
may provide' -- because the language is not expressive
enough to supply a notation for the typesystem it is
in fact using... dynamic typing has pluses (through not
being _forced_ to express what for some reason you
don't _want_ to express, say), but the _inability_ to
express type-features is definitely not a strength...


> What's more? Ah yes, the cast. If you've ever programmed
> in Java, you'll realize that 50 % of the time you're doing
> cast (type conversions), ...

Yes, through a combination of lack of genericity and a
debatable choice regarding coercion syntax.  Visual Basic,
for all of its defects, is defensible in letting the QI call
be implicit when syntactically needed, e.g.
    Dim theGunSlinger as new GunSlinger
    Dim thePainter as Painter
    ...
    Set thePainter = theGunSlinger
This has the same implications as the explicit (Painter)
cast would have in the Java equivalent (and lets you
call the two distinct functions thePainter.Draw() and
theGunSlinger.Draw() -- just as you could in Java, but
might have problems doing if you _couldn't_ express
QueryInterface in some way or other:-).


> >that does not model materials-issues -- which doesn't mean it's
> >*useless*, absolutely not: it's still very useful to model a fluid
> >flow system even in a more abstract way, without consideration of
> >materials' properties;
>
> Abstract way === Functional way !!!!

No, 'more abstract' modeling of a physical system only equals 'more
abstract', that's all.  Fluid flow, in particular, is interesting and
important enough to model at many different abstraction levels;
some important results will already emerge even in highly-abstract
models assuming incompressible fluids and non-turbulent flow --
as you add more aspects to your model, such as turbulence, the
model will be progressively less abstract and quite possibly you
will find out more about the system you're modeling (at the main
price of higher computational cost for a given size of system).

It's perfectly feasible to write simulations at widely varying levels
of abstraction, in either functional or imperative languages (or
in-between ones of various stripes), with typesystems of
whatever kind.


> Having types is liking trying to run a 100 m hurdles race with
> a a heavy chain of  iron in your feet. types are useful but
> I don't want the extreme lack of freedom.

Having a *good* typesystem need be nothing as confining as
that; you don't seem to have much experience using such
typesystems -- I strongly suggest you try out a few before
expressing such trenchant judgments.


Alex






More information about the Python-list mailing list