[Types-sig] Re: Pascal style declarations

Greg Stein gstein@lyra.org
Wed, 15 Dec 1999 02:42:25 -0800 (PST)


On Tue, 14 Dec 1999, Paul Prescod wrote:
> Greg Stein wrote:
> > 
> > "int" is a valid expression, which is valid on the same line after a
> > function definition. For example:
> > 
> >   def funx(x, y): foo() ; return 5
> 
> Well, first, I don't think that we are going to allow functions as
> return type specifications. Use assert for runtime assertions.

I was pointing out that the above code is currently-valid, "real" code. It
is a counter-example to the notion that you can use the "def foo(): type:"
syntax.

I've already stated in the past that type declarators should only be
dotted names.

> Second, Python needs to use look-ahead to tell the difference between
> parentheses used for parsing a tuple and used for bracketing, doesn't
> it?

A very different problem. In both cases, you can have an expression
following that open parentheses. When you see a comma or a right-parent,
then you know what to do with the whole thing.

In the function definition, you don't know whether the thing following the
colon is a type-declarator, or an expression (where an expression is a
valid type of statement, which is part of a suite). In other words, when
the parser starts consuming stuff, it doesn't know whether it is consuming
a "suite" or a "typedecl". Therefore, you must create a pseudo grammar
element which means "it is one of these two, but I don't know YET." At
some point you figure it out and transition to the right part of the
grammar. This is what I meant when I said it would be possible, but not
pretty. I might even venture to say that Guido just plain wouldn't allow
this kind of thing in the Python grammar! :-)

> > We already have expr-based (the "assert" statement) -- we can assert types
> > on expressions anywhere. It is just a little less convenient since we must
> > place the expression value into a temporary variable, assert the type of
> > that, then continue with the expression. The "type-assert operator"
> > simplifies this process dramatically.
> 
> Sure, but why not just use function call syntax? Or maybe Java/C++
> (cast) syntax?

Grammar construction issues. The cast would be difficult -- again the
issue of determining "(" typedecl ")" vs. "(" expr ")" (presuming that a
typedecl cannot be an arbitrary expression. Until you know what the
parse element is (typedecl vs expr), you cannot apply the appropriate
restrictions (e.g. typedecl is only a dotted name or some other new
typedecl syntax that gets invented). C/C++/Java can tell because a name
has an associated name-type (e.g. typedef, variable); once the first
symbol inside that "(" is seen, it can figure out which parsing form is
occurring.

A function call syntax could be possible, but again: is the function part
(before the open paren) an expression or a typedecl? If it looks just like
a function call, then how do you know it is a type assertion? For example:

class Foo:
  ...

x = Foo(y)

Is that an assertion that y is of type Foo, or is it a constructor?

> > Jeremy wrote:
> > > I think I agree with you as far as local variables.  It becomes quite
> > > interesting when you're talking about attributes of objects, e.g. what
> > > is the type of the closed attribute of a builtin file object.  (For
> > > that matter, what is the type of the builtin open function and how
> > > does it differ from a function that returns a StringIO object?)
> > 
> Greg Stein wrote:
> > Ah! Good point. I think this is where interfaces come in. Otherwise, it
> > becomes very difficult to syntactically specify the types of attributes.
> 
> When we specify the types of attributes, we will be talking about those
> attributes by name, not by expression or value. So we need a syntax for
> specifying types of names *and* expressions. If we use function syntax
> for expressions casts then we can reduced the syntactic overload.

As mentioned above: you cannot function syntax (somebody educate me if you
believe otherwise).

All right. I'll modify my statement:

* new syntax to specify param and return types
* new syntax to specify attribute types [as part of an interface defn?]
* type assert operator

Note the specific lack of syntax for specifying *variable* types. We
aren't typing names, just interfaces (and yes, they happen to have names,
but it is truly a different concept right there).

In other words, I don't agree with your statement about typing names and
expressions. I say we provide:

* types for function params, return values
* types for attributes [via interfaces rather than syntax?]
* a type assertion operator
* compile-time (and runtime) checks for the above usages

[ and in a case where all your (called) functions have type decls (e.g.
  os.listdir()), then your code probably doesn't need any assertions since
  inferencing is enough; Guido's case study shows that you can infer
  *everything*, but it would be a lot easier once you have inference 
  boundaries established at the function/method calls. ]

Cheers,
-g

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