Steven D'Aprano wrote:
On Sat, Jan 08, 2022 at 12:59:38AM +0100, jack.jansen@cwi.nl wrote:
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.
In principle, yes. In practice, I think the precedence of "->" might be tricky, particularly if the (int) part discourages people from wrapping the full expression in parentheses.
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?
I assume they *could* be used anywhere, there just wouldn't be huge reasons to do so. Sort of like a string expression can be an entire statement; there just usually isn't much reason (except as a docstring) to do it.
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"?
It provides a useful box around the typing, so that people who are not currently worried about typing can more easily concentrate on the portion they do currently care about.
3. If usable outside of annotations, what runtime effect do they have?
They create a string. Which may or may not be a useful thing to do.
The t-string must evaluate to an object. What object?
A string. The various "let us delay annotation evaluation" proposals have made it clear that the people actually using typing don't want it to slow things down for extra evaluation until they explicitly call for that evaluation, perhaps as part of a special run.
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?
Same answer as number 2 ... it allows typing to be a less intrusive neighbor. I don't think t" " is as good as some sort of braces, but ... we're out of conventional braces available in ASCII.
Likewise, if this is allowed: def func(arr: t"array [1...10] of int") -> str: ...
How many arguments do I pass to func? That is already tricky to see at a glance, but
def func(arr: array [1...10] of int) -> str: ...
is even more difficult to parse. By the time I've mentally attached the "of" and "int" to the indexed (but not really) array that just describes a type, I've forgotten what I was looking for and why.
5. What difference, if any, is there between `t"{expression}"` and `expression`?
In addition to the box (so readers can more easily filter it out), there is also a flag to typing systems saying that they *should* elaborate the string. What they elaborate it into will be very different from a regular string. That won't happen every time the module is imported, but it will happen when the string is actually needed for something. -jJ