[Types-sig] what the heck? (was: Static typing: Towards closure?)

Greg Stein gstein@lyra.org
Thu, 20 Jan 2000 18:45:14 -0800 (PST)


On Fri, 21 Jan 2000, Martijn Faassen wrote:
> Guido van Rossum wrote:
>...
> > I don't like this; the colon still looks best to me.
> 
> This may be because the colon is common in other languages for this
> purpose (and shorter) -- but I am still worried it may not be good in Python.

I'd say consensus is against you here :-). The colon is not ambiguous, is
historically used in declarations, is easy to parse visually, and is quick
to type. Can't be beat :-)

> > > II) The stubbing problem.
> > 
> > > def foo(a, b) -> integer:
> > >    pass
> > > 
> > > will presumabily cause the typechecker to barf. I'm not quite sure if this
> > > is really bad, but I just wanted to bring it to people's attention.
> > 
> > Do this the same say as in Java or C++: return a dummy value.
> 
> Yes, I thought of that, and it may be enough. I just thought to bring the
> breakdown of this common usage to people's attention. :)

"Breakdown of this common usage" ?? Nobody adds ->integer to their Python
code today, so I don't see it as being very common.

If people add that, then they will have to deal with the consequences.
Namely, that they'll get a compile-time error. Nothing wrong with that.

=========

Okay, now we get to the big "HUH?!" in this post...

>...
> > > As the code solidifies we may want to do more checking, so we
> > > can start to explicitize the interfaces. This is similar to the pattern we're
> > > hoping to accomplish by adding static typechecking -- it should be possible
> > > to code in the dynamic way and then tighten up code by adding type annotations
> > > later.
> > 
> > It sounds like a much better thing to do is to leave out all type
> > declarations during prototyping, and add them as you start agreeing on
> > what the interfaces should be.
> 
> You'd have to leave out all type declarations in the code that *uses*
> instances of your classes, then.
> 
> class Foo:
>     def a(self):
>         pass
> 
> class Bar:
>     def a(self):
>         pass
> 
>     def b(self):
>         pass
> 
> # this doesn't seem to work right 
> def use1(obj: Foo | Bar):
>     obj.b() # what happens here? Is this allowed? or is an intersection taken?

It fails. Period. You have stated that "obj" might be a Foo, and we know
that Foo does not implement the "b" method.

What else *should* happen here? I cannot imagine any other reasonable
response from the compiler.

> 
> obj = Foo()
> use1(obj)
> 
> # this gives a compile time error but we can't pass in any instances of 
> # Bar.
> def use2(obj: Foo):
>     obj.b() # this causes the error

Of course. Again, Foo.b does not exist. It should cause an error. You have
also stated that you don't want Bar objects passed.

What's the big deal? Why is this behavior not reasonable?

> # so we have to do this in order to be able to use both Foo and Bar here:
> def use3(obj):
>     obj.b() # run-time error! 

Yes, a run-time error. What's your point?

> # now, if Foo and Bar both stated they implemented the interface Alpha, 
> # the compiler could deal with this:
> def use4(obj: Alpha):
>     obj.b() # compile time error

We don't need Alpha to do this. The original Foo|Bar did the same.

I don't understand your point. The behavior is all very well understood
and quite clean.

> Isn't this a good intermediate step between having an explicit interface
> and not having any interface at all?

I have an idea of what the compiler should be doing (as specified above)
and think that it works very well. I do *not* understand what you are
saying.

Yes, there is an implied interface from the definition of Foo, and the
invocation "obj.b()" fails when used against that implied interface.

BUT: we can entirely omit the word "interface" from this point, and just
state that we know "obj.b() will fail because the Foo class does not
define a 'b' method."

Eliminating the word "interface" from the discussion is Guido's current
position. I believe this is entirely possible. At an implementation level,
I believe there might be an interface-like object, but that's for another
discussion.

> [note: it would also be possible to give Foo and Bar a common baseclass and
> require that type to be used:
> 
> def use5(obj: Common):
>     obj.b() # compile time error, not defined by Common

Yes. What else is supposed to happen?

Really: where are you going with this? I just don't understand.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/