Mark's basic parameter modification would be sufficient for my use-case, the `@composite` decorator in Hypothesis (https://hypothesis.readthedocs.io/en/latest/data.html#composite-strategies).  It looks like I'd annotate that as

# T is a typevar, Ex is a typevar, SearchStrategy is a generic type covariant in Ex
Draw = Callable[[SearchStrategy[T]], T]
def composite(f: Callable[Concatenate[Draw, TParams], Ex]) -> Callable[[TParams], SearchStrategy[Ex]]: ...

If I'm correct, that makes it sufficiently flexible to be actually useful for me (and downstream Hypothesis users), so I'd favor it going into the PEP.

Cheers,
Zac

On Fri, 21 Feb 2020 at 15:22, Guido van Rossum <guido@python.org> wrote:
That sounds reasonable to add to the current PEP. I haven’t thought about enough about whether it would be sufficient for most use cases. Does 
https://github.com/python/mypy/issues/3157 have use cases it couldn’t handle?

On Thu, Feb 20, 2020 at 17:36 Mark Mendoza <mendoza.mark.a@gmail.com> wrote:
Hi Guido and Michael,
Thanks for taking a look at the alternative!  I agree with your overall weighing of the pros and cons of both approaches, and think that we should go ahead with the existing proposal (`ParamSpec`).  I will put an edited version of my message above into the rejected alternatives section of the PEP, and summarize the points folks have made about why we don't want to go that way.

As for parameter modification, I actually can announce that we have a working implementation of basic parameter modification as of today with (https://github.com/facebook/pyre-check/commit/04d4401ee26f92c5b2bb9444d9c5707cf18d7386).  I think this is the extent of what kind of parameter modification will be possible without significantly extending ParamSpecs, so it's worth going into what it can do now.

Big picture we can now safely support adding and removing anonymous arguments from the front of a ParamSpec.  This looks something like this:

Adding arguments:
```
from typing import ParamSpec
from typing.type_variable_operators import Concatenate
TParams = ParamSpec("TParams")
def add_on_arguments(f: Callable[TParams, str]) -> Callable[Concatenate[str, bool, TParams], int]:
  def inner(first: str, second: bool, /, *args: TParams.args, **kwargs: TParams.kwargs) -> int:
    use(first, second)
    s = f( *args, **kwargs)
    return int(s)
  return inner
```

Removing arguments
```
def remove_arguments(f: Callable[Concatenate[int, bool, TParams], str]) -> Callable[TParams, int]:
  def inner( *args: TParams.args, **kwargs: TParams.kwargs) -> int:
    s = f(75, True, *args, **kwargs)
    return int(s)
  return inner
```

Transforming the type of a finite number of arguments
```
def change_arguments(f: Callable[Concatenate[int, bool, TParams], str]) -> Callable[Concatenate[float, string, TParams], int]:
  def inner( first: float, second: string, /, *args: TParams.args, **kwargs: TParams.kwargs) -> int:
    use(first, second)
    s = f(75, True, *args, **kwargs)
    return int(s)
  return inner
```

What this approach doesn't support is creating new named arguments, or interacting with keyword-only arguments.  These are still problematic for the reasons outlined in the rejected alternatives section.

With that being said:
* Do you think this is sufficient flexibility?
* Do you think this behavior should be included in the PEP or postponed to a follow up?
_______________________________________________
Typing-sig mailing list -- typing-sig@python.org
To unsubscribe send an email to typing-sig-leave@python.org
https://mail.python.org/mailman3/lists/typing-sig.python.org/
--
--Guido (mobile)
_______________________________________________
Typing-sig mailing list -- typing-sig@python.org
To unsubscribe send an email to typing-sig-leave@python.org
https://mail.python.org/mailman3/lists/typing-sig.python.org/