The Artima Developer Community
Sponsored Link

Weblogs Forum
Optional Static Typing -- Stop the Flames!

79 replies on 6 pages. Most recent reply: Feb 4, 2008 12:52 PM by Wolfgang Lipp

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 79 replies on 6 pages [ « | 1 2 3 4 5 6 | » ]
SX

Posts: 2
Nickname: shrimpx
Registered: Jan, 2005

Re: Optional Static Typing -- Stop the Flames! Posted: Jan 9, 2005 9:40 PM
Reply to this message Reply
Advertisement
I just want to say that the idea of static typing was a sound one and it should by no means be abandoned.

First of all, everyone seems to be ignoring the _optional_ part of it. I agree that Python shouldn't become statically typed overnight (or never), but if you can make it an option that many people will enjoy, why not?!

Second, static typing has definite uses and a long, successful history. As a Web programmer programming in Perl and Python, I witnessed countless errors and crashes that exhibited themselves weeks or months after I did the coding, and which my unit tests didn't catch. If your program passes a correctly implemented type check, you have a formal proof that your code will never crash due to a particular set of errors. That's pretty nice!

Third, ideas are in the very early stages, so giving up or slandering are premature. Let it cook for a couple of months, check out ideas in other languages -- Haskell's type classes have not been mentioned in the whole interface debacle, for example.

Finally, I have to critique what many people seem to think Python culture means. Somehow, Python has become "a really really really dynamic language" whose dynamic ways should in now way be messed with, unless of course they were made even more dynamic. For some reason I thought that Python was more than that.

I've always seen Python as a "bridge" langauge, willing with no hesitation to borrow, assimilate, and immitate in an effort to preserve and improve expressiveness and usefulness. In this, it has always managed to maintain originality and freshness. List comprehensions? They were borrowed directly from Miranda and Haskell. Generators? Lazy languages have them mandatorily and many imperative languages have generator libraries and call them "lazy lists." filter? reduce? map? lambdas? closures? That's functional programming!

Python is, in my opinion, the one language that makes an ongoing effort to bring advanced programming to the mainstream in a nice, elegant manner, and is underestimated by the research community as well as its own. Please, let it grow and expand and don't hinder it with cultural drivel, blaming it that it's robbing you of your sense of identity.

People are very afraid of big changes but are willing to admit one little change at a time. Eventually, you will end up with an optional annotation for every little disjoint, scattered feature that could have been nicely unified in a sound type system.

With a powerful module system and static typing, Python would be very, very hard to beat in ANY context.

Thanks, Guido, for Python.

John M Camara

Posts: 15
Nickname: camara
Registered: Dec, 2004

Re: Optional Static Typing -- Stop the Flames! Posted: Jan 9, 2005 10:37 PM
Reply to this message Reply
SX

> As a Web programmer programming in
> Perl and Python, I witnessed countless errors and crashes
> that exhibited themselves weeks or months after I did the
> coding, and which my unit tests didn't catch.

Sounds like you need to write better unit tests. Don't blame these problems on the lack of type checking. To do so, shows you have a lack of understanding on the use or application of unit tests.

John

Guido van van Rossum

Posts: 359
Nickname: guido
Registered: Apr, 2003

Re: Optional Static Typing -- Stop the Flames! Posted: Jan 9, 2005 11:55 PM
Reply to this message Reply
[SX]
> > As a Web programmer programming in
> > Perl and Python, I witnessed countless errors and
> > crashes that exhibited themselves weeks or months
> > after I did the coding, and which my unit tests
> > didn't catch.

[John M Camara]
> Sounds like you need to write better unit tests. Don't
> blame these problems on the lack of type checking. To do
> so, shows you have a lack of understanding on the use or
> application of unit tests.

Now, now, John. We all know static typing is no panacea. But neither is unit testing. They each have their strenghts and weaknesses, and SX has a point: one of Python's strength is its borrowing from many other languages and paradigms (and another strength is my restraint in so borrowing :-).

Alex Martelli

Posts: 3
Nickname: aleax
Registered: Jan, 2005

Re: Providing standard protocols Posted: Jan 10, 2005 6:12 AM
Reply to this message Reply
> In my wild and crazy fantasies, i wish that Python could
> do either or both of these things:
>
> 1. To implement a class that provides the complete mapping
> protocol, i only have to write 3-4 basic methods. When i
> derive my class from a standard Mapping interface, the
> rest of the methods get filled in for me.

The time machine seems to have solved this one for you: see UserDict.DictMixin which appears to be exactly what you ask.


Alex

Ka-Ping Yee

Posts: 24
Nickname: ping
Registered: Dec, 2004

Re: Providing standard protocols Posted: Jan 10, 2005 4:04 PM
Reply to this message Reply
> > 1. To implement a class that provides the complete mapping
> > protocol, i only have to write 3-4 basic methods. When i
> > derive my class from a standard Mapping interface, the
> > rest of the methods get filled in for me.
>
> The time machine seems to have solved this one for you:
> see UserDict.DictMixin which appears to be exactly what
> you ask.

That's not quite what i'm talking about. I'm aware that this functionality can be brought in with a mix-in class; what i'm suggesting is that this be part of the standard interface. For example, if a Mapping interface is introduced, i'd like it to do this as part of its definition so we can be confident that all implementors have it. More generally, i'd like this to be part of the way interfaces typically work, not just to have a couple of one-off mix-ins in the library for mappings and sequences.

Both of the things i suggested in the original comment, which i guess you could call API-widening-by-interface and API-widening-by-adaptation, are aimed at improving flexibility and resilience by giving the client of an object more assurance that all the methods will be present and have the expected semantics.

Does that make sense?

Guido van van Rossum

Posts: 359
Nickname: guido
Registered: Apr, 2003

Re: Providing standard protocols Posted: Jan 10, 2005 4:42 PM
Reply to this message Reply
> Both of the things i suggested in the original comment,
> which i guess you could call API-widening-by-interface and
> API-widening-by-adaptation, are aimed at improving
> flexibility and resilience by giving the client of an
> object more assurance that all the methods will be present
> and have the expected semantics.

-1

Since you keep defending this...

I don't think that anybody who has experience with Pythonic interfaces (e.g. the Zope and Twisted folks) has tried this yet, so I'm reluctant to accept either proposal. The 2nd one can be prototyped within the framework of an PEP 246 implementation; in fact, PEP 246 won't stop any interface from implementing this.

I'm not keen on your proposal for having code in interfaces. It introduces some ambiguity, and you will need to mark which methods are *not* optional (even if it were possible by analyzing all the code to automatically determine this, I think the human reader would be better off if it was explicit). Also, it means the code in the interface can't be used for invariant testing (or else it would introduce even more ambiguity).

Personally, I expect that this will be useful mostly in "toy" examples or for specific backwards compatibility situations, where the adaptation trick may be handy.

Kurt B. Kaiser

Posts: 1
Nickname: kbk
Registered: Jan, 2005

Re: Optional Static Typing -- Stop the Flames! Posted: Jan 10, 2005 5:05 PM
Reply to this message Reply
Eiffel has several levels of assertions associated with DBC:

preconditions
postconditions
invariants
loop invariants & variants
checks [groups of assertions]

These can be enabled in increasing order using the LACE compiler control. Or switched completely off for performance reasons.

Alex Martelli

Posts: 3
Nickname: aleax
Registered: Jan, 2005

Re: Providing standard protocols Posted: Jan 10, 2005 5:06 PM
Reply to this message Reply
> > > 1. To implement a class that provides the complete
> mapping
> > > protocol, i only have to write 3-4 basic methods.
> When i
> > > derive my class from a standard Mapping interface,
> the
> > > rest of the methods get filled in for me.
> >
> > The time machine seems to have solved this one for you:
> > see UserDict.DictMixin which appears to be exactly what
> > you ask.
>
> That's not quite what i'm talking about. I'm aware that
> this functionality can be brought in with a mix-in class;
> what i'm suggesting is that this be part of the
> standard interface. For example, if a Mapping

So, basically, you want to make the interface into an abstract class instead, offering "template methods" which call back to a few lower-level "hook" methods -- just like, say, DictMixin does today, except that DictMixin is more flexible. If you have, say, a readonly mapping, you can still use DictMixin to give you many readonly "richer" methods -- if somebody tries to call a read-write "richer" method, it will fail one or two levels down when DictMixin's implementation calls to the __setitem__ (say) which you don't implement (or in which you raise an exception). You can also use DictMixin without claiming to conform to the dictionary protocol. For example, consider shelve -- can it really be said to conform to the dictionary protocol, when it can only accept strings, not arbitrary hashables, as keys? For DictMixin it doesn't matter: thanks to signature-based polymorphism, it can still work just fine to provide higher-level methods by Template DP even under such restrictions.

So, even if Mapping (carefully and painstakingly segregated -- at least -- into readonly and readwrite variants), RandomAddressableSequence (ditto), etc etc, all came with the relevant mixins bundled in, I would still want to have those mixins available in the standard library separately from the interfaces, because pragmatically speaking they're still very useful.

> interface is introduced, i'd like it to do this as part of
> its definition so we can be confident that all
> implementors have it. More generally, i'd like this to be
> part of the way interfaces typically work, not just to
> have a couple of one-off mix-ins in the library for
> mappings and sequences.

Maybe a special mechanism is warranted to let a "pure" interface (where the contents of methods should really represent checks, pre/post conditions, and the like, rather than default implementations) indicate one (or more, see below) "supporting mixins" to be added to classes claiming to implement the interface. I believe that the existence of a good set of pure interfaces and supporting mixins for the typical protocols found in the standard library is more likely to be the determinant of how interfaces will typically be designed, rather than any such "bundling" mechanism, but that's just a guess, and I could be wrong. In any case, the ability to use the mixins separately from the interfaces would remain important, as above indicated.


> Both of the things i suggested in the original comment,
> which i guess you could call API-widening-by-interface and
> API-widening-by-adaptation, are aimed at improving
> flexibility and resilience by giving the client of an
> object more assurance that all the methods will be present
> and have the expected semantics.
>
> Does that make sense?

I think it does, and indeed it prompts me to raise the ante by going back to my original idea, which was to have in Python a closer equivalent to Haskell's typeclasses, rather than to pure interfaces or abstract classes.

A typeclass is more powerful and flexible than an abstract class because it need not specify which methods are abstract, aka lower-level, in other terms exactly which methods need to be supplied by an object to claim compliance (and to possibly get the Template DP implementations of the others in terms of the ones it does supply). As a toy example:

typeclass IWriteable:
def write(self, onething):
self.writelines([onething])
def writelines(self, manythings):
for onething in manythings:
self.write(onething)

this looks like write and writelines are mutually recursive, but that's not what it means: it means that a class claiming to implement IWriteable must supply either write or writelines (it may also supply both, for performance reasons). If it only supplies EITHER one, the other is supplied Template DP - like from the typeclass.

If we had typeclass, then we'd need the metaclass to determine the dependencies at typeclass level, then when a concrete class is being built, find out which methods the concrete class supplies and pick the others appropriately (or give an error if the concrete class just doesn't supply a sufficient baseset of concrete methods).

An almost equivalent alternative might be to have an interface be able to specify several mixins depending on the sets of concrete methods supplied by the concrete class which is claiming to implement the interface; this would offer less automatism, more explicitness and control, perhaps more readability, and also accomplish the key purpose of ensuring the mixins are also available for separate use.

I don't really know which of the alternatives on a growing scale of depth and elegance -- provide no special mechanism, provide a special mechanism that can only deal with one mixin, provide one that can deal with several, implement full-fledged typeclasses... -- would give the best bang for the buck. Maybe we should widen this discussion by moving to python-dev...


Alex

SX

Posts: 2
Nickname: shrimpx
Registered: Jan, 2005

Re: Optional Static Typing -- Stop the Flames! Posted: Jan 10, 2005 9:00 PM
Reply to this message Reply
>Sounds like you need to write better unit tests. Don't blame these
>problems on the lack of type checking. To do so, shows you have
>a lack of understanding on the use or application of unit tests.

Are you saying that you can write a spread of unit tests that basically guarantees correctness? Sorry, but that's not possible, even if you have a better understanding of applications of unit tests than I do.

I hope we can all agree that writing unit tests to catch type errors is utterly superfluous.

Jim Fulton

Posts: 3
Nickname: j1m
Registered: Jan, 2005

Re: implements vs "subclassing" Posted: Jan 11, 2005 6:00 AM
Reply to this message Reply
I would really hate to see subclassing used because it mixes concerns. Subclasses provide implementation. Interfaces provide specification. I think it would be very confusing for the reader of a class definition to mix the base classes from interfaces.

> I don't mind adding new syntax, but I'd like to avoid
> introducing two new reserved words. (The
> implements(...) function uses a horrible hack which I
> don't want to standardize.)

I understand your distaste, however, this has worked our very very well from a readability point of view. So much so, that we've recently added an adapts function that uses the same trick:

class FooBar:

adapts(IFoo)
implements(IBar)

...

I and others find this very readable. I wonder if there is some way, in the long term to make this or someting close to it work without the hack.

Or, perhaps this is a job for class decorators:

@adapts(IFoo)
@implements(IBar)
class FooBar:
...

But please don't mix interfaces and base classes.

Ka-Ping Yee

Posts: 24
Nickname: ping
Registered: Dec, 2004

Re: implements vs "subclassing" Posted: Jan 11, 2005 7:04 AM
Reply to this message Reply
> I would really hate to see subclassing used because it
> mixes concerns. Subclasses provide implementation.
> Interfaces provide specification.

Okay, i hear your concern. I'm trying to raise an issue that seems worth discussing, but i don't intend to claim that i have the only or the best answer.

I agree with you that interfaces are for specification. The question is, how does an interface specify the relationship of one method to another? For example, how would an interface say, "In order for your class to properly implement the mapping interface, its get(key, default) method should behave like __getitem__(key), except that if the key is not present it should return default instead of failing."

There are a few ways one might do this, of which code in the interface is only one. Putting code in the interface ensures that by default the methods will have the expected relationship. Alternatively, you could have a mechanism for the interface to specify an associated mix-in class and have implementations automatically inherit from that class. Or instead of automatic inheritance you could just give implementors a way to say "I want the default mix-in". Or you could just establish a convention for specifying the mix-in in the interface documentation, and let the implementor figure it out. Or you could establish a naming convention that relates the name of the mix-in to the name of the interface. Or you could explain the expected behaviour of all the extra methods in the docstring for each method. Or you could decide this isn't worth it, and do nothing.

Anyway, i'm sure there are other possibilities. I just wanted to see if this is something anyone cares about.

Of greater practical concern, i think, is the scenario: Your function expects an argument that behaves like a mapping. You would like to have the convenience of using the expanded mapping interface (e.g. get(), setdefault(), etc.). How do you do this safely? Ideally, you would like your function to work with previously written mappings that might not implement the entire expanded interface.

Specifying the expanded API in the interface or providing a mix-in are ways of getting at this problem on the implementation end. On the client end, it would be nice to have a mechanism to widen an object's interface. I'm curious to know whether such a mechanism would be interesting to you.

(Without any additional mechanism, inheritance doesn't help on the client end; you would have to write a separate class that expands the API by delegation, like UserDict. Would interfaces typically come in three parts, like dict, UserDict, and DictMixin?)

Ka-Ping Yee

Posts: 24
Nickname: ping
Registered: Dec, 2004

Re: Providing standard protocols Posted: Jan 11, 2005 7:14 AM
Reply to this message Reply
> I'm not keen on your proposal for having code in interfaces.

All right.

> you will need to mark which methods are *not* optional

If i may ask, what's your current thinking on how adapt() will behave with an interface? I wasn't clear about whether it should require the interface to be listed in __implements__, require the presence of all the methods with the correct signatures, either, or both.

At what point (compilation, instantiation, adaptation, call, etc.) do you think it's best to have missing methods cause exceptions?

Dmitry Vasiliev

Posts: 1
Nickname: hdima
Registered: Jan, 2005

Re: implements vs "subclassing" Posted: Jan 11, 2005 8:05 AM
Reply to this message Reply
> > I don't mind adding new syntax, but I'd like to avoid
> > introducing two new reserved words. (The
> > implements(...) function uses a horrible hack which I
> > don't want to standardize.)
>
> I understand your distaste, however, this has worked our
> very very well from a readability point of view. So much
> so, that we've recently added an adapts function that uses
> the same trick:
>

> class FooBar:
>
> adapts(IFoo)
> implements(IBar)
>
> ...
>

> I and others find this very readable. I wonder if there
> is some way, in the long term to make this or someting
> close to it work without the hack.

Just an idea:

class FooBar(adapts(IFoo), implements(IBar)):
pass

The metaclass should know about adapts and implements objects.

Guido van van Rossum

Posts: 359
Nickname: guido
Registered: Apr, 2003

Re: Providing standard protocols Posted: Jan 11, 2005 11:02 AM
Reply to this message Reply
> If i may ask, what's your current thinking on how
> adapt() will behave with an interface? I
> wasn't clear about whether it should require the interface
> to be listed in __implements__, require the
> presence of all the methods with the correct signatures,
> either, or both.

This is really a question for PEP 246, not for me, but I believe that it is entirely up to the objects implementing __adapt__ and __conform__. If either wants to cheat, that's fine -- after all, this is Python, and there may be a reason to cheat (maybe the interface is wrong).

Guido van van Rossum

Posts: 359
Nickname: guido
Registered: Apr, 2003

Re: implements vs "subclassing" Posted: Jan 11, 2005 11:07 AM
Reply to this message Reply
> class FooBar(adapts(IFoo), implements(IBar)):
> pass

I like this, not just because it means that adapts() and implements() can be builtins rather than keywords, but also because it can be extended to other functionality without requiring adding even more keywords.

(Come to think of it, that was, subconsciously, my main reason for disliking implements as a keyword: there are other relationships between classes and interfaces and requiring a keyword for each relationship feels like a waste of keywords, since the keywords have no use elsewhere in the syntax.)

Flat View: This topic has 79 replies on 6 pages [ « | 1  2  3  4  5  6 | » ]
Topic: Optional Static Typing -- Stop the Flames! Previous Topic   Next Topic Topic: Setting Up for Emulation


Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us