[Types-sig] Re: syntax and compile/run -time

Paul Prescod paul@prescod.net
Tue, 04 Jan 2000 12:03:07 -0500


Greg Stein wrote:
> 
> On Mon, 3 Jan 2000, Paul Prescod wrote:
> > Greg Stein wrote:
> > > Dividing the language into pieces is simply dividing it. I see no rational
> > > reason for doing so, but many reasons to keep everything clean and
> > > integrated.
> >
> > Dividing the language is inevitable. The question is whether to do it
> > "up front" or subtly through cryptic error messages.
> 
> You are presuming that the alternative to "up front" is "cryptic error
> messages". Again: this is FUD.

It is my opinion that if you try to pretend that things that are static
are dynamic, then all you do is delay the shock of finding out that
things don't work as you expected.

> > I don't want the type-checker flagging valid code with warnings (unless
> > you turn -Wall) and I don't want it silently ignoring code like the
> > above because it doesn't understand it.
> 
> I agree. I've been presuming that a number of warnings will only be
> flagged with -Wall. Whether my explanation on what happens with your
> example truly issues a warning or not... fine-tuning.

Okay, then we can put aside warning messages. Code like this is just
"valid":

a=callSomeFunction()
decl foo def(x: a)->None

Code that calls foo is not statically type checkable. What is the point
of using static type checking syntax if this cannot be static type
checked? They is just as easy:

a=callSomeFunction()
def foo( x ):
	assert a in x.__interfaces__

I don't consider it intuitive to use static type checking syntax for
something that must be evaluated at runtime. A static declaration that
can't be checked statically just isn't useful.

> Your syntax with a "typedef" statement attempts to avoid the problem by
> restricting the syntax to an arbitrary subset of Python. My proposal
> allows people to use similar, limited syntax *or* to use complex stuff for
> complex, runtime operations.

I don't restrict runtime manipulation of type objects. I just think that
it is done through a reflection API similar to the traceback API or the
parse tree API.

> Fine. We can declare your example "illegal". 

But doesn't "this should be legal" fall naturally out of the syntax? I
think that the whole point of the syntax is that types are just runtime
objects and can be treated just as runtime objects.

> I was simply trying to state
> that it *can* be legal. Look at my words, quoted above. I was attempting
> to move it to #3 -- runtime only. Even though we move it there, the
> type-checker can tell that the user may have thought it fell into #1, so
> it can issue a warning.
> 
> But hey: this is what Guido calls, to paraphase, "appropriate error
> messages." Some fine-tuning is all.

I'm having trouble arguing here because we haven't even decided whether
it is illegal or not.

If it is illegal, then that is confusing because what's the point of
treating type objects as ordinary Python objects with ordinary
assignments if they are going to be restricted in some contexts?

If it is legal, you said in the paragraph above that it is reasonable
that the user is going to be confused about what is going on and how it
works. Since it is legal, there will be no error message so the user is
on her own unless she thinks to use "lint mode".

> ==> "incomplete" classes and interfaces may be declared

I've never pre-declared a function or class in Python. Don't you think
that predeclaring interfaces is un-Pythonic?

> decl incomplete class foo_private
> decl incomplete class foo_object

Ugh.

> Oh, bunk. I was attempting to make it actually *work* for the user. In
> your model, it would just punt. You are creating artificial limitations,
> and you're doing it through a partitioned syntax. Neither is desirable.

I see a partitioned syntax as a virtue. It is very analogous to the
distinction between languages that feel that they have to make regular
expressions "first class" integrated syntax and those that say: "regular
expressions use a different model than everything else. They will be a
sub-language with special syntax and semantics." 

> If somebody says:
> 
>   MyComplicatedType = doSomething()
> 
>   def foo(x: MyComplicatedType):
>     ...
> 
> Why should we prevent them? 

Because declaring a static type check that cannot be statically
evaluated is not a reasonable action, IMO. It will most often be an
accident. It is not Pythonic to allow the dubious action and then depend
on a "lint mode" to warn of the dubiousness.

I say, let them do it, but tell them they
> aren't going to get compile-time assistance with the construct.
> 
> Keep the syntax clean. Provide flexibility. Let the developer know if they
> have done something suspicious.

"Do or do not do. There is no try." - Yoda
"Legal or illegal. There is no suspicious." - Paul

Can we put aside warnings? I think that we agree that they are not a
solution.

The only way to "let the developer know" when they have done something
supicious is through error messages. That means that the construct is
illegal. As soon as we make a few of these constructs illegal, we are
back to essentially a sub-language proposal.

If we do NOT make it illegal then we have to allow a compiler to
silently accept it and the programmer is on his own.

 Paul Prescod