[Types-sig] Re: feedback, round 2 (LONG) (Re: PyDL RFC 0.4)

Martijn Faassen m.faassen@vet.uu.nl
Wed, 05 Jan 2000 11:31:02 +0100

Paul Prescod wrote: 
> Greg Stein wrote:
[snip snip]

> Okay, but C revolves around a concept of types. Python (arguably) is
> supposed to revolve around a concept of interfaces. "I don't care if you
> hand me a file thing, as long as it BEHAVES like a file thing." Our
> static type checker is really a static interface checker. For the rare
> case when we really care about types, we'll use the implied,
> implementation-specific interface.

I agree with this very strongly; I reached about the same conclusion
before christmas, but didn't find time to clean up my text and post it.
It is interesting that you people seem to be going in the same direction
-- this would imply we're on the right track.
> > We should. I want to parameterize classes. Don't force me to extract an
> > interface from my class definition -- I want an implicit, parameterized
> > interface derived from my class definition and its inline declarations.
> I see this as:
> "Future Directions: At some point in the future, PyDL files will likely
> be generated from source code using a combination of declarations within
> Python code and some sorts of interface deduction and inferencing based
> on various kinds of assignment."
> Note that I have also provided no syntax for specifying the types of
> functions in the function declarations. You make a separate declaration
> with the types.

My take is that all classes should imply an interface. I'm going back to
my pre-christmas thoughts here. :) If we split the types namespace from
the variable namespace (I'm in favor of this), then the implied
interface of the class can be the same name (in the same module context
etc) as the name of the class.


class Foo:

implies implicit interface Foo which is extracted from all the inline
declarations of Foo.

> > The basic premise is that I will use classes as *both* an interface
> > definition and an implementation. To that end, I want all the features of
> > a standard inteface definition to be available through my class
> > definition.
> But an interface is an interface. A class is a type. A type can be used
> as an "implementation specific interface" but this is a bad habit that
> leads to weirdness like functions that work on file objects but blow up
> on FTP download streams.

Again I'm going back to my previous thoughts: you can actually derive
interface definitions almost 'for free'. Now we do explicitly name
interfaces with something like 'conforms':

class A conforms GetPutInterface:
    decl member a: Int
    decl member b: Int

    def get()->Int:

    def put(d: Int):

    def bar():

class B conforms GetPutInterface:
    decl member a: Int
    decl member c: Int

    def get()->Int:
    def put(d: Int):
    def foo():

Now the structure of GetPutInterface can be automatically derived from
the union of the interfaces of these two classes. You *don't* explicitly
define GetPutInterface anywhere (though you can):

interface GetPutInterface:
    decl member a: Int

    def get()->Int

    def put(d: Int)

So, you get the common interface with minimal changes to the code.

Of course in many cases you do want to say what the interface is
explicitly; otherwise you could (by mistake) limit union of the
interfaces too much (even to nothing at all). You make sure a
constructed interface is not too large by making sure you have a class
with a minimal interface that conforms to the same interface. You can
make sure a constructed interface isn't too small by explicitly stating
the interface.

But you don't have to explicitly state the interface. This makes current
Python code very easy to adapt to interfaces, you can add interfaces in
an incremental way and slowly 'harden' your code to use explicit
interfaces. But you don't have to; you just have to say a class conforms
to an interface, and they're there.

So far my last century thoughts. :)

> I agree that there should someday be a syntax for extracting an
> implementation *independent* interface from a class as a convenience but
> then we need to get into issues of "public/private" and so forth. After
> all, it will almost never be the case that a class's interface will be
> 100% identical to its implementation signature.

My scheme also neatly avoids this problem. I initially thought you'd
need access control as well, but if you construct interfaces as the
union of two class interfaces (the ones always implied by the class that
have the same name as the class), your interface is exactly as big as it
has to be (unless of course you did something wrong). It doesn't include
'private' data that's only used in the implementation, at least not as
easily. It may of course be possible that data or functions of the exact
same name and signature are used very differently in two classes. In
that case you do want the ability to explicitly define an interface.

Anyway, summary:

* each class implies an interface with the same name
* each class can be explicitly pecified to conform to an interface of
some name
* this interface does not have to be explicitly defined somewhere; it
can be
derived from the union of all classes that state they conform to this
* this interface *can* be explicitly defined somewhere.
* in this scheme, we're dealing with 'static interface checking'.