<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Mon, Aug 1, 2016 at 10:14 PM Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">What makes you respond so vehemently to `a: float`?<br></blockquote><div><br></div><div>First reaction.  It doesn't actually seem too bad now.  It is already legal to just say `a` as a statement so this isn't much different.</div><div><br></div><div>def f():</div><div><span style="line-height:1.5">  a</span></div><div><span style="line-height:1.5"><br></span></div><div><span style="line-height:1.5">is already legal.  So `a: List[float]` would at least be meaningful rather than a meaningless statement that any linter should question. :)</span></div><div><span style="line-height:1.5"> </span><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
The `def` keyword has been proposed before, but *I* have a vehement<br>
response to it; `def` is for functions.<br>
<br>
The Cython syntax may live forever in Cython, but I don't want to add<br>
it to Python, especially since we already have function annotations<br>
using `var: type = default` -- variable declarations must somehow<br>
rhyme with this.<br></blockquote><div><br></div><div>I agree, cdef is their own mess. :)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
The `local` keyword isn't horrible but would still require a<br>
`__future__` import and a long wait, which is why I'm exploring just<br>
`var: type = value`. I think we can pull it off syntactically, using a<br>
trick no more horrible than the one we already employ to restrict the<br>
LHS of an assignment even though the grammar seen by the parser is<br>
something like `expr_stmt: testlist ('=' testlist)*` (at least it was<br>
something like this long ago -- it's more complex now but the same<br>
idea still applies, since the official parser is still LR(1)).<br>
<br>
Regarding scopes, I like the way mypy currently does this -- you can<br>
only have a `# type` comment on the first assignment of a variable,<br>
and scopes are flat as they are in Python. (Mypy is really<br>
anticipating a syntax for variable declarations here.) Seems we agree<br>
on this, at least.<br></blockquote><div><br></div><div>-gps</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
On Mon, Aug 1, 2016 at 4:39 PM, Gregory P. Smith <<a href="mailto:greg@krypto.org" target="_blank">greg@krypto.org</a>> wrote:<br>
><br>
> On Mon, Aug 1, 2016 at 2:32 PM Guido van Rossum <<a href="mailto:guido@python.org" target="_blank">guido@python.org</a>> wrote:<br>
>><br>
>> PEP 484 doesn't change Python's syntax. Therefore it has no good<br>
>> syntax to offer for declaring the type of variables, and instead you<br>
>> have to write e.g.<br>
>><br>
>> a = 0  # type: float<br>
>> b = []  # type: List[int]<br>
>> c = None  # type: Optional[str]<br>
>><br>
>> I'd like to address this in the future, and I think the most elegant<br>
>> syntax would be to let you write these as follows:<br>
>><br>
>> a: float = 0<br>
>> b: List[int] = []<br>
>> c: Optional[str] = None<br>
>><br>
>> (I've considered a 'var' keyword in the past, but there just are too<br>
>> many variables named 'var' in my code. :-)<br>
>><br>
><br>
> My first impression of this given the trivial int and str examples is... Why<br>
> are you declaring types for things that are plainly obvious?  I guess that's<br>
> a way of saying pick better examples. :)  Ones where the types aren't<br>
> implied by obvious literals on the RHS.<br>
><br>
> Your examples using complex types such as List[int] and Optional[str] are<br>
> already good ones as that can't be immediately inferred.<br>
><br>
> b: str = module.something(a)<br>
><br>
> is a better example as without knowledge of module.something we cannot<br>
> immediately infer the type and thus the type declaration might be considered<br>
> useful to prevent bugs rather than annoying read and keep up to date.<br>
><br>
> I predict it will be more useful for people to declare abstract<br>
> interface-like types rather than concrete ones such as int or str anyways.<br>
> (duck typing ftw)  But my predictions shouldn't be taken too seriously.  I<br>
> want to see what happens.<br>
><br>
>><br>
>> There are some corner cases to consider. First, to declare a<br>
>> variable's type without giving it an initial value, we can write this:<br>
>><br>
>> a: float<br>
><br>
><br>
> I don't like this at all.  We only allow pre-declaration without an<br>
> assignment using keywords today.  the 'local' suggestion others have<br>
> mentioned is worth consideration but I worry any time we add a keyword as<br>
> that breaks a lot of existing code.  Cython uses 'cdef' for this but we<br>
> obviously don't want that as it implies much more and isn't obvious outside<br>
> of the cython context.<br>
><br>
> You could potentially reuse the 'def' keyword for this.<br>
><br>
> def a: List[float].<br>
><br>
> This would be a surprising new syntax for many who are used to searching<br>
> code for r'^\s*def' to find function definitions.  Precedent: Cython already<br>
> overloads its own 'cdef' concept for both variable and function/method use.<br>
><br>
> Potential alternative to the above def (ab)use:<br>
><br>
> def a -> List[float]<br>
> def a List[float]<br>
> def List[float] a  # copies the Cython ordering which seems to derive from C<br>
> syntax for obvious reasons<br>
><br>
> But the -> token really implies return value while the : token already<br>
> implies variable type annotation.  At first glance I'm not happy with these<br>
> but arguments could be made.<br>
><br>
>> Second, when these occur in a class body, they can define either class<br>
>> variables or instance variables. Do we need to be able to specify<br>
>> which?<br>
>><br>
>> Third, there's an annoying thing with tuples/commas here. On the one<br>
>> hand, in a function declaration, we may see (a: int = 0, b: str = '').<br>
>> On the other hand, in an assignment, we may see<br>
>><br>
>> a, b = 0, ''<br>
>><br>
>> Suppose we wanted to add types to the latter. Would we write this as<br>
>><br>
>> a, b: int, str = 0, ''<br>
>><br>
>> or as<br>
>><br>
>> a: int, b: str = 0, ''<br>
>><br>
>> ??? Personally I think neither is acceptable, and we should just write it<br>
>> as<br>
>><br>
>> a: int = 0<br>
>> b: str = ''<br>
><br>
><br>
> Disallowing ": type" syntax in the presence of tuple assignment seems simple<br>
> and wise to me. Easy to parse. But I understand if people disagree and want<br>
> a defined way to do it.<br>
><br>
>> but this is a slight step back from<br>
>><br>
>> a, b = 0, ''   # type: (int, str)<br>
>><br>
>> --<br>
>> --Guido van Rossum (<a href="http://python.org/~guido" rel="noreferrer" target="_blank">python.org/~guido</a>)<br>
><br>
><br>
> When thinking about how to spell this out in a PEP, it is worth taking into<br>
> account existing ways of declaring types on variables in Python. Cython took<br>
> the "Keyword Type Name" approach with "cdef double j" syntax.<br>
> <a href="http://cython.readthedocs.io/en/latest/src/quickstart/cythonize.html" rel="noreferrer" target="_blank">http://cython.readthedocs.io/en/latest/src/quickstart/cythonize.html</a><br>
><br>
> Is it an error to write the following (poor style) code declaring a type for<br>
> the same variable multiple times:<br>
><br>
> c: int = module.count_things(x)<br>
> compute_thing(c)<br>
> if c > 3:<br>
>   c: str = module.get_thing(3)<br>
>   <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>('end of thing 3: %s', c[-5:])<br>
> do_something(c)<br>
><br>
> where c takes on multiple types within a single scope? static single<br>
> assignment form would generate a c', c'', and union of c' and c'' types for<br>
> the final do_something call to reason about that code.  but it is entirely<br>
> doable in Python and does happen in unfortunately real world messy code as<br>
> variables are reused in bad ways.<br>
><br>
> My preference would be to make it an error for more than one type to be<br>
> declared for the same variable.<br>
> First type ever mentioned within the scope wins and all others are<br>
> SyntaxError worthy.<br>
> Assigning to a variable in a scope before an assignment that declares its<br>
> type should probably also be a SyntaxError.<br>
><br>
> -gps<br>
><br>
<br>
<br>
<br>
--<br>
--Guido van Rossum (<a href="http://python.org/~guido" rel="noreferrer" target="_blank">python.org/~guido</a>)<br>
</blockquote></div></div>