On 7 Oct 2021, at 18:41, S Pradeep Kumar <gohanpra@gmail.com> wrote:

Note that we considered and rejected using a full def-signature syntax like
````
(record: PurchaseRecord, permissions: List[AuthPermission], /) -> FormattedItem
````
because it would be more verbose for common cases and could lead to subtle bugs; more details in [3].

Is this also why re-using an actual callable at a type was rejected?

I always found the following more obvious:


def data_to_table(d: Iterable[Mapping[str, float]], *, sort: bool = False, reversed: bool = False) -> Table:
    ...


@dataclass
class Stream:
    converter: data_to_table | None

    def add_converter(self, converter: data_to_table) -> None:
        self.converter = converter


This solves the following problems with the `(P, Q) -> R` proposal:
- how should this look like for "runtime" Python
- how should we teach this
- how can we express callables with complex signatures

One disadvantage of this is that now arguments HAVE TO be named which raises questions:
- should they be considered at type checking time? 
- how to express "I don't care"?

To this I say:
- yes, they should be considered at runtime (because kwargs have to be anyway)
- ...unless they begin with an underscore

This still leaves a minor problem that you can't have more than one argument literally named `_` so you'd have to do `_1`, `_2`, and so on. I don't think this is a big problem.

In fact, forcing users to name callable arguments can be added as a fourth advantage to this design: making the annotations maximally informative to the human reader.

The only remaining disadvantage that can't be addressed is that you can't create an *inline* callable type this way. I don't think this is a deal breaker as neither TypedDicts, Protocols, nor for this matter any PlainOldClasses can be defined inline inside a type annotation.


- Ł