[Types-sig] RFC Comments

Paul Prescod paul@prescod.net
Tue, 28 Dec 1999 05:42:48 -0500


>         No. I think you have to make up your mind here.
> You must choose. Either 'List' is an interface,
> or, it is an interface generator, it cannot be both.
> [In your terminology, you can't use a parameterised interface
> where a fully resolved one is required; so List cannot
> be both partly unresolved and also fully resolved]

Okay, I will use your terminology.

>         Yeah, but you would do well to get out of the habit
> of saying 'can' and 'may'. Use the word 'shall'. Meaning,
> that the damn thing is REQUIRED to do something :-)
> Dont give permission. Specify requirements.

I expect to rewrite the specification from scratch (with grammar) before
I am done. Consider this version a prototype. Once we have the design
down I will generate the normative spec.

>         Point 0: Paul, list the predefined names like Integer,
>         or whatever. Say if they are keywords or plain identifiers.

I've been putting this off because there are some tricky issues around
file objects.

> > Note that the arguments can be either interfaces or simple Python
> > expressions. A "simple" Python expression is an expression that does
> > not involve a function call.
> 
>         No. See above. List(Int) already involves a 'function call'.

List is (according to your terminology) an interface generator, not a
function.

> > 5. Declare un-modifiability:
> >
> > const [const Array( Integer )]
> >
> > (the semantics of un-modifiability need to be worked out)
> 
>         Again, forget it, for the moment.

Isn't that what I did? :)

> This one can be real nasty.

Agreed.

>         No. Use a distinct keyword like 'include'.
> There is a good reason for this: consider embedded declarations.
> Then it is
> 
>         a) impossible to load an interface but not the module
>         b) impossible to load a module, but not the interface
> 
> A separate keyword resolves the ambiguity when embedded:
> 
>         import X # load the module
>         include X # load the interface
> 
> Note that importing a module implicitly loads the interface anyhow.
> However, it will do so in an appropriate namespace.

I don't understand your model of namespaces and inclusions. I don't
understand mine either so don't feel bad.

> It is necessary to load interfaces even when modules
> are not imported (by the client module). There are other
> ways to get at stuff from a module than import it.
> For example, a function call f() can return an object whose
> class is defined in a module X the calling module has
> not imported: we may want to type check the returned
> object, which requires importing the module X's interface
> -- without importing the module X itself.

We can have an API like:

load_interface("foo")

I don't think that the needs of a very specific tool like a static type
checker should drive syntax to that extent. The other 99% of code will
never do an "include" and the keyword will be wasted.

>         I am already using ! not : here, following Greg Stein.

I'm going to presume that that isn't a backwards-compatibility argument.
:)

> There are enough ":"'s in python already :-)

Debatable. I would also be amenable to "as", "is" or "isa". "!" means
not to me.

> > What we are really defining is the constructor. The signature of the
> > created object can be described in an interface declaration.
> 
>         Not good enough. The semantics of class instance
> attributes would be 'when you assign to this attribute,
> it had better have this type'. This doesn't mean that
> you can be sure an access gives that type,
> the attribute might not exist. This defeats optimisation.

The attribute will either have the type or something like "undefined".
Since undefined is not a "useful" value, you can optimize away.

> Your spec would break this code. You can argue that your
> spec is a better spec -- but it isn't Python compatible.

Agreed. I will clarify that the behavior of "dropped off" functions is
just a suggestion of how Python 2 might be improved using the features
of the new object.

>         FYI: In Viper, uninitialised, statically
> declared variables are initialised with the special object PyInitial.
> Another special object, PyTerminal, also exists. These objects
> are useful in the internal workings of the implementation,
> for bounding things (i.e. as sentinels). For example,
> it makes calculating max( .... ) much easier. [PyInitial
> is less than all other objects]

It sounds like None re-invented. My only reason for wanting a new object
(not None) is because None is way too flexible. You could pass a None
through ten thousand lines of code accidently. So I wouldn't want
Undefined to be useful to "max" or anything else other than "is", "str"
and "repr".

>         I _think_ you mean that the interface dictionary
> is 'per module'? And you can refer to an interface
> in another module with other.interfx notation?

True.

> > The runtime should not allow an assignment or function call to violate
> > the declarations in the PyDL file. In an "optimized speed mode" those
> > checks would be disabled.
> 
>         I think you have to think very carefully about what
> constitues an error here: see my posts about errors in python.
> It is not acceptable to specify that an exception be thrown.
> That would NOT permit an optimiser to elide checks, except
> when it could prove they were not needed.
>
>         Much better, you deem a violating program
> is not valid, and then the language processor can do whatever
> it wants: it may raise an exception, or it may core dump,
> or it may reject the program early.

I will consider this. An alternate technique is to list allowed recovery
strategies:

"It is an error if this leaves more than one match. An XSLT processor
may signal the error; if it does not signal the error, it must recover
by choosing, from amongst the matches that are left, the one that occurs
last in the stylesheet."

"It is an error if instantiating the content of
xsl:processing-instruction creates nodes other than text nodes. An XSLT
processor may signal the error; if it does not signal the error, it must
recover by ignoring the offending nodes together with their content."

 Paul Prescod