Skip to content

A possible syntax for a function type with a varargs argument list #540

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gvanrossum opened this issue Dec 20, 2014 · 8 comments
Closed

Comments

@gvanrossum
Copy link
Member

I just skimmed the README for Reticulated Python (https://github.com/mvitousek/reticulated). They have a useful hack to spell the type of a function with varargs or other dynamic hacks in the argument list: a normal function type is spelled e.g. Function([Int, Int], Float); a function type with a varargs argument list is spelled e.g. Function(DynParameters, Float). In mypy this would be Function[DynParameters, float]. (Or pick some other name for DynParameters.)

@JukkaL
Copy link
Collaborator

JukkaL commented Dec 20, 2014

Something like this would be useful. See also #393; Any and None (I don't really like the latter) have been proposed as alternatives to DynParameters. Here are more ideas: AnyArgs, AnyParameters.

If we want go a bit further, we could have a special kind of type variable that matches any function argument signature. This would let use represent additional things, such as a function that maps any function to the same function but with a None return value:

Args = Var('Args', kind='args')

def nonefy(func: Callable[Args, Any]) -> Callable[Args, None]: ...

def f(x: int) -> int: 
    print(x)
    return x

g = nonefy(f)   # This has type Callable[[int], None] (but it also accepts a keyword arg)

An additional refinement would allow a type variable that maps to a variable-length list of types (unlike the above proposal, it wouldn't know about keyword arguments etc.), and this variable could also be used in Callable as argument types. For example:

TL = Var('TL', kind='typelist')
X = Var('X')

def f(f: Callable[TL, X], t: Tuple[TL]) -> X:   # Or Callable[[TL], X]
    return f(*t)   # OK!

c = f(chr, (32,))   # Okay, type of c is str
f(pow, (2, 3))  # Okay
f(pow, (2,))  # Error

At least the latter would probably be useful for higher-order functions.

@gvanrossum
Copy link
Member Author

Hm... The use cases for your Args typevar seem meager, and the TL looks confusingly like a function of one arg. (Especially Tuple[TL] seems wrong, it appears to be a 1-tuple whose item is a TL.) I'd like to have something simpler, a single predefined name that just means "callable with any arguments at all. including keyword args." Reusing Any or None for this feels like it would easily be confused (I'm thinking here of someone seeing Callable[Any, int] and thinking it means Callable[[Any], int]).

Instead, let's have a predefined name AnyArgs that can be used instead of a list of argument types, e.g. Callable[AnyArgs, int] is a function with an unconstrained argument list returning an int. AnyArgs would just be a marker object that doesn't have any behavior (it wouldn't be considered a type or class, and would be illegal everywhere else).

@ambv
Copy link
Contributor

ambv commented Jan 7, 2015

Was the use of ellipsis considered?

Callable[..., int]

@gvanrossum
Copy link
Member Author

Ah, I actually like Callable[..., int]. I can't recall if it was considered before or not (I think we only rejected None and Any, because both are valid types (None being a shortcut for NoneType) and Callable[Any, int] looks like a typo for Callable[[Any], int].

Jukka, what do you think? Does Callable[..., int] work for mypy?

@JukkaL
Copy link
Collaborator

JukkaL commented Jan 8, 2015

I like Callable[..., int] -- the only issue I see is a need for a Python 2 alternative. If we are going to use ... in more than one construct, maybe we should define typing.Ellipsis or typing.Dots as an alternative.

@gvanrossum
Copy link
Member Author

Fortunately that's also valid Python 2 syntax (in Python 2 it's only valid in a __getitem__ context -- and this is one. :-)

Let's call this settled then.

@JukkaL
Copy link
Collaborator

JukkaL commented Jan 8, 2015

Cool, I didn't remember that :-)

@JukkaL
Copy link
Collaborator

JukkaL commented May 17, 2015

Closing as this is a dupe of #393.

@JukkaL JukkaL closed this as completed May 17, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants