Thanks to visit codestin.com
Credit goes to github.com

Skip to content

TypeVar example in PEP is confusing #39

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
JukkaL opened this issue Jan 15, 2015 · 5 comments
Closed

TypeVar example in PEP is confusing #39

JukkaL opened this issue Jan 15, 2015 · 5 comments

Comments

@JukkaL
Copy link
Contributor

JukkaL commented Jan 15, 2015

[I think Guido pointed this out elsewhere, but maybe this should be addressed separately here so that it won't be forgotten.]

The following type variable constraint example from the PEP is confusing:

from typing import Iterable
X = TypeVar('X')
Y = TypeVar('Y', Iterable[X])
def filter(rule: Callable[[X], bool], input: Y) -> Y:
...

I think this could be written equivalently without having a constraint:

from typing import Iterable
X = TypeVar('X')
def filter(rule: Callable[[X], bool], input: Iterable[X]) -> Iterable[X]:
...

Also, if this is similar to the values keyword argument to mypy's typevar, having a type variable with a single value would be equivalent to having a type alias (since subtypes are not valid), so the only interesting use cases would have 2 or more constraints.

There is actually no non-trivial example of using constraints in the PEP. I suggest adding an AnyStr example, as this seems like the most common use case for constraints (at least of the sort supported by mypy right now). Maybe the discussion should mention how this is different from bounded polymorphism/quantification as in Java, for example, as this is probably the most non-mainstream feature introduced in the PEP.

@brakhane
Copy link

Does that mean that there is no way to specify that two non union types must/will be the same? In the above example, I would have expected that the first filter function is guaranteed to return a file object if called with a file object, but the second definition could return a sequence instead.

That would be indeed unexpected and should be documented. It also seems inconsistent:

X = TypeVar("X")
def copy(original: X) -> X

Y  = TypeVar("Y", Iterable[X])
def copy_it(original: Y) -> Y

Both declarations look identical, but while the first one will guarantee that isinstance(original, copy) is true, the second one doesn't; copy_it((1,2,3,4,5)) could return a list, for example.

@gvanrossum
Copy link
Member

Yes, generic types and type variables need to be explained better. I think you did get the distinction between constrained and unconstrained type variables right (though your words are a bit confusing).

The best example of constrained type variables is AnyStr. See the explanation of this in http://mypy.readthedocs.org/en/latest/generics.html .

I would also like to point out that requiring a function to return an object of the exact same type as an argument is usually unreasonable, since being able to extract the type (e.g. x.__class__) is not sufficient to be able to create an instance. (How would you know the constructor signature?) There is some discussion of this in python/mypy#539 (search for "Eugene").

@JukkaL
Copy link
Contributor Author

JukkaL commented Jan 17, 2015

Usually the only case where returning an object of the exactly same type as an argument is reasonable when the returned object is one of the arguments (or contained within an argument). So this is okay because we just pass through an object:

T = TypeVar('T')
def first(x: Sequence[T]) -> T: return x[0]

@vlasovskikh
Copy link
Member

See also #1.

@JukkaL
Copy link
Contributor Author

JukkaL commented Apr 14, 2015

Rewrote the example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants