PEP 695: Fix/improve syntax & content of Language Survey section (#2725)
This commit is contained in:
parent
82072755b5
commit
754c8fb1f6
191
pep-0695.rst
191
pep-0695.rst
|
@ -840,19 +840,19 @@ may be useful when considering future extensions to the Python type system.
|
|||
C++
|
||||
---
|
||||
|
||||
C++ uses angle brackets in combination with keywords "template" and
|
||||
"typename" to declare type parameters. It uses angle brackets for
|
||||
C++ uses angle brackets in combination with keywords ``template`` and
|
||||
``typename`` to declare type parameters. It uses angle brackets for
|
||||
specialization.
|
||||
|
||||
C++20 introduced the notion of generalized constraints, which can act
|
||||
like protocols in Python. A collection of constraints can be defined in
|
||||
a named entity called a "concept".
|
||||
a named entity called a ``concept``.
|
||||
|
||||
Variance is not explicitly specified, but constraints can enforce variance.
|
||||
|
||||
A default type argument can be specified using the "=" operator.
|
||||
A default type argument can be specified using the ``=`` operator.
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
// Generic class
|
||||
template <typename>
|
||||
|
@ -896,7 +896,9 @@ Java
|
|||
----
|
||||
|
||||
Java uses angle brackets to declare type parameters and for specialization.
|
||||
The "extends" keyword is used to specify an upper bound.
|
||||
By default, type parameters are invariant.
|
||||
The ``extends`` keyword is used to specify an upper bound. The ``super`` keyword
|
||||
is used to specify a contravariant bound.
|
||||
|
||||
Java uses use-site variance. The compiler places limits on which methods and
|
||||
members can be accessed based on the use of a generic type. Variance is
|
||||
|
@ -904,7 +906,7 @@ not specified explicitly.
|
|||
|
||||
Java provides no way to specify a default type argument.
|
||||
|
||||
::
|
||||
.. code-block:: java
|
||||
|
||||
// Generic class
|
||||
public class ClassA<T> {
|
||||
|
@ -912,6 +914,9 @@ Java provides no way to specify a default type argument.
|
|||
|
||||
// Generic method
|
||||
public <S extends Number> void method1(S value) { }
|
||||
|
||||
// Use site variance
|
||||
public void method1(ClassA<? super Integer> value) { }
|
||||
}
|
||||
|
||||
|
||||
|
@ -919,16 +924,16 @@ C#
|
|||
--
|
||||
|
||||
C# uses angle brackets to declare type parameters and for specialization.
|
||||
The "where" keyword and a colon is used to specify the bound for a type
|
||||
The ``where`` keyword and a colon is used to specify the bound for a type
|
||||
parameter.
|
||||
|
||||
C# uses declaration-site variance using the keywords "in" and "out" for
|
||||
C# uses declaration-site variance using the keywords ``in`` and ``out`` for
|
||||
contravariance and covariance, respectively. By default, type parameters are
|
||||
invariant.
|
||||
|
||||
C# provides no way to specify a default type argument.
|
||||
|
||||
::
|
||||
.. code-block:: c#
|
||||
|
||||
// Generic class with bounds on type parameters
|
||||
public class ClassA<S, T>
|
||||
|
@ -951,20 +956,21 @@ TypeScript
|
|||
----------
|
||||
|
||||
TypeScript uses angle brackets to declare type parameters and for
|
||||
specialization. The "extends" keyword is used to specify a bound. It can be
|
||||
combined with other type operators such as "keyof".
|
||||
specialization. The ``extends`` keyword is used to specify a bound. It can be
|
||||
combined with other type operators such as ``keyof``.
|
||||
|
||||
TypeScript uses declaration-site variance. Variance is inferred from
|
||||
usage, not specified explicitly. TypeScript 4.7 will introduce the ability
|
||||
to specify variance using "in" and "out" keywords. This was added to handle
|
||||
extremely complex types where inference of variance was expensive.
|
||||
usage, not specified explicitly. TypeScript 4.7 introduced the ability
|
||||
to specify variance using ``in`` and ``out`` keywords. This was added to handle
|
||||
extremely complex types where inference of variance was expensive,
|
||||
yet the maintainers state that is useful for increasing readability.
|
||||
|
||||
A default type argument can be specified using the "=" operator.
|
||||
A default type argument can be specified using the ``=`` operator.
|
||||
|
||||
TypeScript supports the "type" keyword to declare a type alias, and this
|
||||
TypeScript supports the ``type`` keyword to declare a type alias, and this
|
||||
syntax supports generics.
|
||||
|
||||
::
|
||||
.. code-block:: typescript
|
||||
|
||||
// Generic interface
|
||||
interface InterfaceA<S, T extends SomeInterface1> {
|
||||
|
@ -991,11 +997,11 @@ Scala
|
|||
-----
|
||||
|
||||
In Scala, square brackets are used to declare type parameters. Square
|
||||
brackets are also used for specialization. The "<:" and ">:" operators
|
||||
brackets are also used for specialization. The ``<:`` and ``>:`` operators
|
||||
are used to specify upper and lower bounds, respectively.
|
||||
|
||||
Scala uses use-site variance but also allows declaration-site variance
|
||||
specification. It uses a "+" or "-" prefix operator for covariance and
|
||||
specification. It uses a ``+`` or ``-`` prefix operator for covariance and
|
||||
contravariance, respectively.
|
||||
|
||||
Scala provides no way to specify a default type argument.
|
||||
|
@ -1003,7 +1009,7 @@ Scala provides no way to specify a default type argument.
|
|||
It does support higher-kinded types (type parameters that accept type
|
||||
type parameters).
|
||||
|
||||
::
|
||||
.. code-block:: scala
|
||||
|
||||
|
||||
// Generic class; type parameter has upper bound
|
||||
|
@ -1036,17 +1042,16 @@ Swift
|
|||
Swift uses angle brackets to declare type parameters and for specialization.
|
||||
The upper bound of a type parameter is specified using a colon.
|
||||
|
||||
Swift uses declaration-site variance, and variance of type parameters is
|
||||
inferred from their usage.
|
||||
Swift doesn't support generic variance; all type parameters are invariant.
|
||||
|
||||
Swift provides no way to specify a default type argument.
|
||||
|
||||
::
|
||||
.. code-block:: swift
|
||||
|
||||
// Generic class
|
||||
class ClassA<T> {
|
||||
// Generic method
|
||||
func method1<X>(val: T) -> S { }
|
||||
func method1<X>(val: T) -> X { }
|
||||
}
|
||||
|
||||
// Type parameter with upper bound constraint
|
||||
|
@ -1061,23 +1066,33 @@ Rust
|
|||
|
||||
Rust uses angle brackets to declare type parameters and for specialization.
|
||||
The upper bound of a type parameter is specified using a colon. Alternatively
|
||||
a "where" clause can specify various constraints.
|
||||
a ``where`` clause can specify various constraints.
|
||||
|
||||
Rust uses declaration-site variance, and variance of type parameters is
|
||||
typically inferred from their usage. In cases where a type parameter is not
|
||||
used within a type, variance can be specified explicitly.
|
||||
Rust does not have traditional object oriented inheritance or variance.
|
||||
Subtyping in Rust is very restricted and occurs only due to variance with
|
||||
respect to lifetimes.
|
||||
|
||||
A default type argument can be specified using the "=" operator.
|
||||
A default type argument can be specified using the ``=`` operator.
|
||||
|
||||
::
|
||||
.. code-block:: rust
|
||||
|
||||
// Generic class
|
||||
struct StructA<T> {
|
||||
struct StructA<T> { // T's lifetime is inferred as covariant
|
||||
x: T
|
||||
}
|
||||
|
||||
fn f<'a>(
|
||||
mut short_lifetime: StructA<&'a i32>,
|
||||
mut long_lifetime: StructA<&'static i32>,
|
||||
) {
|
||||
long_lifetime = short_lifetime;
|
||||
// error: StructA<&'a i32> is not a subtype of StructA<&'static i32>
|
||||
short_lifetime = long_lifetime;
|
||||
// valid: StructA<&'static i32> is a subtype of StructA<&'a i32>
|
||||
}
|
||||
|
||||
// Type parameter with bound
|
||||
struct StructB<T: StructA> {}
|
||||
struct StructB<T: SomeTrait> {}
|
||||
|
||||
// Type parameter with additional constraints
|
||||
struct StructC<T>
|
||||
|
@ -1089,56 +1104,55 @@ A default type argument can be specified using the "=" operator.
|
|||
// Generic function
|
||||
fn func1<T>(val: &[T]) -> T { }
|
||||
|
||||
// Explicit variance specification
|
||||
use type_variance::{Covariant, Contravariant};
|
||||
|
||||
struct StructD<A, R> {
|
||||
arg: Covariant<A>,
|
||||
ret: Contravariant<R>,
|
||||
}
|
||||
|
||||
// Generic type alias
|
||||
type MyType<T> = StructC<T>
|
||||
type MyType<T> = StructC<T>;
|
||||
|
||||
|
||||
Kotlin
|
||||
------
|
||||
|
||||
Kotlin uses angle brackets to declare type parameters and for specialization.
|
||||
The upper bound of a type is specified using a colon.
|
||||
By default, type parameters are invariant. The upper bound of a type is
|
||||
specified using a colon.
|
||||
Alternatively, a ``where`` clause can specify various constraints.
|
||||
|
||||
Kotlin supports declaration-site variance where variance of type parameters is
|
||||
explicitly declared using "in" and "out" keywords. It also supports use-site
|
||||
explicitly declared using ``in`` and ``out`` keywords. It also supports use-site
|
||||
variance which limits which methods and members can be used.
|
||||
|
||||
Kotlin provides no way to specify a default type argument.
|
||||
|
||||
::
|
||||
.. code-block:: kotlin
|
||||
|
||||
// Generic class
|
||||
class ClassA<T> { }
|
||||
class ClassA<T>
|
||||
|
||||
// Type parameter with upper bound
|
||||
class ClassB<T: SomeClass1> { }
|
||||
class ClassB<T : SomeClass1>
|
||||
|
||||
// Contravariant and covariant type parameters
|
||||
class ClassC<in S, out T> { }
|
||||
class ClassC<in S, out T>
|
||||
|
||||
// Generic function
|
||||
fun func1<T>() -> T {}
|
||||
fun <T> func1(): T {
|
||||
|
||||
// Use site variance
|
||||
val covariantA: ClassA<out Number>
|
||||
val contravariantA: ClassA<in Number>
|
||||
}
|
||||
|
||||
// Generic type alias
|
||||
typealias<T> = ClassA<T>
|
||||
typealias TypeAliasFoo<T> = ClassA<T>
|
||||
|
||||
|
||||
Julia
|
||||
-----
|
||||
|
||||
Julia uses curly braces to declare type parameters and for specialization.
|
||||
The "<:" operator can be used within a "where" clause to declare
|
||||
The ``<:`` operator can be used within a ``where`` clause to declare
|
||||
upper and lower bounds on a type.
|
||||
|
||||
::
|
||||
.. code-block:: julia
|
||||
|
||||
// Generic struct; type parameter with upper and lower bounds
|
||||
struct StructA{T} where Int <: T <: Number
|
||||
|
@ -1151,6 +1165,62 @@ upper and lower bounds on a type.
|
|||
// Alternate form of generic function
|
||||
function func2(v::Container{T} where T <: Real)
|
||||
|
||||
Dart
|
||||
----
|
||||
|
||||
Dart uses angle brackets to declare type parameters and for specialization.
|
||||
The upper bound of a type is specified using the ``extends`` keyword.
|
||||
By default, type parameters are covariant.
|
||||
|
||||
Dart supports declaration-site variance, where variance of type parameters is
|
||||
explicitly declared using ``in``, ``out`` and ``inout`` keywords.
|
||||
It does not support use-site variance.
|
||||
|
||||
Dart provides no way to specify a default type argument.
|
||||
|
||||
.. code-block:: dart
|
||||
|
||||
// Generic class
|
||||
class ClassA<T> { }
|
||||
|
||||
// Type parameter with upper bound
|
||||
class ClassB<T extends SomeClass1> { }
|
||||
|
||||
// Contravariant and covariant type parameters
|
||||
class ClassC<in S, out T> { }
|
||||
|
||||
// Generic function
|
||||
T func1<T>() { }
|
||||
|
||||
// Generic type alias
|
||||
typedef TypeDefFoo<T> = ClassA<T>;
|
||||
|
||||
Go
|
||||
--
|
||||
|
||||
Go uses square brackets to declare type parameters and for specialization.
|
||||
The upper bound of a type is specified after the name of the parameter, and
|
||||
must always be specified. The keyword ``any`` is used for an unbound type parameter.
|
||||
|
||||
Go doesn't support variance; all type parameters are invariant.
|
||||
|
||||
Go provides no way to specify a default type argument.
|
||||
|
||||
Go does not support generic type aliases.
|
||||
|
||||
.. code-block:: go
|
||||
|
||||
// Generic type without a bound
|
||||
type TypeA[T any] struct {
|
||||
t T
|
||||
}
|
||||
|
||||
// Type parameter with upper bound
|
||||
type TypeB[T SomeType1] struct { }
|
||||
|
||||
// Generic function
|
||||
func func1[T any]() { }
|
||||
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
@ -1162,7 +1232,8 @@ Summary
|
|||
| C++ | template | n/a | n/a | = | n/a | n/a |
|
||||
| | <> | | | | | |
|
||||
+------------+----------+---------+--------+----------+-----------+-----------+
|
||||
| Java | <> | extends | | | use | inferred |
|
||||
| Java | <> | extends | | | use | super, |
|
||||
| | | | | | | extends |
|
||||
+------------+----------+---------+--------+----------+-----------+-----------+
|
||||
| C# | <> | where | | | decl | in, out |
|
||||
+------------+----------+---------+--------+----------+-----------+-----------+
|
||||
|
@ -1171,15 +1242,21 @@ Summary
|
|||
+------------+----------+---------+--------+----------+-----------+-----------+
|
||||
| Scala | [] | T <: X | T >: X | | use, decl | +, - |
|
||||
+------------+----------+---------+--------+----------+-----------+-----------+
|
||||
| Swift | <> | T: X | | | decl | inferred |
|
||||
| Swift | <> | T: X | | | n/a | n/a |
|
||||
+------------+----------+---------+--------+----------+-----------+-----------+
|
||||
| Rust | <> | T: X, | | = | decl | inferred, |
|
||||
| | | where | | | | explicit |
|
||||
| Rust | <> | T: X, | | = | n/a | n/a |
|
||||
| | | where | | | | |
|
||||
+------------+----------+---------+--------+----------+-----------+-----------+
|
||||
| Kotlin | <> | T: X | | | use, decl | inferred |
|
||||
| Kotlin | <> | T: X, | | | use, decl | in, out |
|
||||
| | | where | | | | |
|
||||
+------------+----------+---------+--------+----------+-----------+-----------+
|
||||
| Julia | {} | T <: X | X <: T | | n/a | n/a |
|
||||
+------------+----------+---------+--------+----------+-----------+-----------+
|
||||
| Dart | <> | extends | | | decl | in, out, |
|
||||
| | | | | | | inout |
|
||||
+------------+----------+---------+--------+----------+-----------+-----------+
|
||||
| Go | [] | T X | | | n/a | n/a |
|
||||
+------------+----------+---------+--------+----------+-----------+-----------+
|
||||
| Python | [] | T: X | | | decl | inferred |
|
||||
| (proposed) | | | | | | |
|
||||
+------------+----------+---------+--------+----------+-----------+-----------+
|
||||
|
|
Loading…
Reference in New Issue