[Python-3000] Type parameterization (was: Re: Type annotations: annotating generators)

Guido van Rossum guido at python.org
Fri May 19 06:13:18 CEST 2006


On 5/18/06, Collin Winter <collinw at gmail.com> wrote:
[...]
> BDFL syntax has generally used "Sometype[parameterizer]" to indicate
> type parameterization. With this Generator example, you've gone ahead
> and implicitly addressed several of the more general questions I had
> about parameterization (but since explicit is better than
> implicit...):
>
> 1. As above, I've occasionally seen "Sometype(parameterizer)" used to
> indicate parameterization, but the bracket-based syntax predominates;
> can I get a pronouncement endorsing the bracket version as "official"?

I'm pragmatic. You can't use list(int) because list is a concrete type
so that would call the list constructor. So list[int] it is. This also
happens to match Eiffel, but I chose it primarily because I wanted
something that's not new syntax and yet somewhat resembled C++ or Java
SomeContainer<T>.

But since it's just an expression, I'm not against using functional
notation if for some reason square brackets don't quite work (e.g.
when a keyword argument would be desirable).

> 2. You've used keyword parameters in the above parens-based example; I
> take it these will be legal in all parameterizations?

Yes. The important thing is that THE SYNTAX FOR PARAMETER ANNOTATIONS
IS JUST AN EXPRESSION. So it can use any syntactic feature of
expressions.

> If yes, this would offer a solution to something I haven't seen
> addressed in any blog posts: how to parameterize dict. Plenty of
> examples show parameterizations of list, tuple, set, etc using
> positional arguments.
>
> Use of positional arguments to parameterize dict, e.g., dict[str,
> Number], is ugly, but keyword arguments would allow the prettier
> dict[key=str, value=Number] (which might also be another use case for
> the proposed keyword-only arguments).

Maybe you didn't find all blog posts, or maybe I really didn't mention
it, but I personally prefer dict[str, Number]. There really can't be
much confusion over what these mean for anyone who knows what a dict
is.

> Now for some more specific questions:
>
> 3. What does list[] mean (i.e., brackets without a parameterizer)? Is
> it an error? An empty list (the list *must* be empty)? Is it different
> from a type annotation of list (without brackets)?

It's a syntax error:

Python 2.5a1 (trunk, Apr  9 2006, 21:00:48)
[GCC 2.96 20000731 (Red Hat Linux 7.3 2.96-113)] on linux2
Type "help", "copyright", "credits" or "license" for more information.]
>>> list[]
  File "<stdin>", line 1
    list[]
         ^
SyntaxError: invalid syntax
>>>

To answer the implicit question: list (without brackets) would mean
the same as list[object].

> Similarly, can you do something like list[Number, String] to assert
> that the list instance must have an length evenly divisible by two and
> consisting of alternating Numbers and Strings? (That is, [4, 'abc',
> 7.0, 'foo'] is valid but [4, 'abc', 7.0] is not.)

No. I don't like using lists that way anyway. I think that's probably
an idiom from Perl or Tcl?

> 4. In one blog post, tuple[Number] is described as creating a tuple of
> arbitrary length with Number elements, with something like (Number *
> Number * String) used to create a 3-tuple. Could we drop the cartesian
> product notation for this latter usage and use tuple[Number, Number,
> String] instead?

Yes, please.

> > Generator[Number] and Generator(Number) could mean the same thing
> > assuming Generator is not a real type like list but a pseudo type only
> > used for type annotations, like Sequence, Mapping, Iterator etc.
>
> This gets into another question: will user-defined annotation classes
> be able to use the same parameterization notation?

Yes. In fact believe I once wrote a metaclass derived from type that
would let you create arbitrary user-defined parameterizable classes,
and I used this to prototype a few parts of my notation. I think it
went like this:

class List(list):
  __metaclass__ = ParameterizedType
  __parameters__ = ["T"]

class Dict(dict):
  __metaclass__ = ParameterizedType
  __parameters__ = ["T1", "T2"]

I'm not 100% sure about the __parameters__ thing, and I'm not sure how
you'd do tuple[<varargs>] but I'm sure we can find a way.

(I don't recall where I put the code; it's probably easier to recreate
it from scratch anyway, but I doubt I have time tonight -- I'm just
back from a week off-line and have some catching up to do.)

> I'd like to see the typechecking machinery ignore differences like
> "real type" v "pseudo type", looking only at whether, zB, a
> __parameterize__ method is present. Using __parameterize__ method (or
> some other name) allows maximum flexibility with respect to type
> parameterization.
>
> For example, the built-in list type might not allow the patterned
> parameterization I asked about above. A user might choose to subclass
> list to provide this, giving the subclass a __parameterize__ method
> something like:
>
> @classmethod
> def __parameterize__(cls, *vargs):
>     ....

I'm not sure what you're up to here -- maybe it's a reference to
something you did in your own system? But I agree that that kind of
subclassing (perhaps at the metaclass level) ought to be possible.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)


More information about the Python-3000 mailing list