> > If I can make a wild suggestion: why not create a little language
> > for type specifications?
Any time we are tempted to prefix a question with "Why not ...", the
question is backwards. The right question is, "why should we ...".
OK -- we should create a little language for type specifications because it's proving to be really difficult to cleanly express types with Python's current allowable syntax. This is documented by the PEP that started this thread -- if you have to expand the syntax of Python to make clean expression of typing possible, it's time to make a new language., rather than complicating Python.
... we should be conservative when it comes
to language changes (including syntax).
exactly -- we are now faced with changing language syntax to satisfy the needs of one particular optional corner of Python -- we should be particularly very careful about that!
(and it's not just callables -- there was a long thread in python-ideas about a yeear (?) ago about extending indexing syntax, that started with the needs of typing.
> > If you look at other programming languages you’ll see that the “type
> > definition sub-language” is often completely different from the
> > “execution sub-language”
Yes, and that makes other programming languages harder to use and harder
to learn.
I would argue that hat's because you have to learn type specifications at all -- not because they have different syntax.
IN fact, in my very limited C experience I found it very confusing that often declare a function was the same as defining it -- which is this bit of code doing? In practice the declarations are usually in a header file, but that's not (I think) required by the language. IT would be less confusing if the type declaration were clearly different.
But anyway, right now in PYthon, type declarations use standard Pyhton syntax, but they use it in a non-convensional way. Is it more or less confusing that:
list[int]
means "a list full of integers"
and
a_list[an_int] means return the value (which could be any type) of the item at index an_int?
Does the same syntax with very different meanings make it easier or harder to learn??
For example, the arrow syntax for Callable `(int) -> str` (if accepted)
could be a plain old Python expression, usable anywhere the plain old
Python expression `Callable[[int], str]` would be.
but what would `` -> `` mean ?!?! if all it meant was create an instance of the Callable class, then you have a typing mini-language that can be used anywhere -- more or less confusing ?!?
Or it could be used as a new way to spell lambda -- I know a lot of folks would like a cleaner way to spell lambda, but would that really make the language simpler?
I think a good way of putting it is that the typing module defines a
little DSL (Domain Specific Language) for type hints, but annotations
themselves are just Python expressions.
OK -- and if you had t" " -- then that would be a Python expression, too :-)
> > What if we created a little language that is clearly flagged, for
> > example as t”….” or t’….’? Then we could simply define the
> > typestring language to be readable, so you could indeed say t”(int,
> > str) -> bool”. And we could even allow escapes (similar to
> > f-strings) so that the previous expression could also be specified,
> > if you really wanted to, as t”{typing.Callable[[int, str], bool}”.
The following are not rhetorical questions. I don't know the answers,
which is why I am asking.
1. Are these t-strings only usable inside annotations, or are they
expressions that are usable everywhere?
as you say -- not much point if they aren't usable anywhere -- why not?
2. If only usable inside annotations, why bother with the extra prefix
t" and suffix "? What benefit do they give versus just the rule
"annotations use this syntax"?
Agreed - -though I think there is a certain clarity about it -- also, it would make a the transition a bit easier if the idea was adopted.
3. If usable outside of annotations, what runtime effect do they have?
The t-string must evaluate to an object. What object?
I'm just spit-balling here, but maybe an "Annotation Object" -- which could be a pre-compiled or normalized version of the annotation string. kind of like a pre-compiled regex, maybe? I have not idea if MyPy and friends have sucha. normalized version, but it does seem like it could be handy.
4. If the syntax allowed inside the t-string is specified as part of the
Python language definition, why do we need the prefix and suffix?
E.g. if we can write:
# Equivalent to T = Callable[[int], str]
T = t"(int) -> str"
and have the arrow syntax defined by the language, then surely the
prefix and suffix is redundant.
I think the idea is that , e.g. -> wouldn't be allowed outside an t-string and other things, like [] might mean sometihng different.
But in the end, if they are not going to be pre-processed, anon only allowed in annotations, then yes, no nead for the t"" at all.
I think the first question is whether a typing language is a good idea at all -- then we can worry about these details.
This is not the case with f-strings, where they actually do add
something to the code: `f"{expr}"` is not the same as `expr`.
right, and f-strings ultimately evaluate to normal strings as well.
-CHB
--