diff --git a/spec/API_specification/function_and_method_signatures.md b/spec/API_specification/function_and_method_signatures.md new file mode 100644 index 000000000..31af7da5d --- /dev/null +++ b/spec/API_specification/function_and_method_signatures.md @@ -0,0 +1,53 @@ +# Function and method signatures + +Function signatures in this standard adhere to the following: + +1. Positional parameters must be + [positional-only](https://www.python.org/dev/peps/pep-0570/) parameters. + Positional-only parameters have no externally-usable name. When a function + accepting positional-only parameters is called, positional arguments are + mapped to these parameters based solely on their order. + + _Rationale: existing libraries have incompatible conventions, and using names + of positional parameters is not normal/recommended practice._ + +2. Optional parameters must be + [keyword-only](https://www.python.org/dev/peps/pep-3102/) arguments. + + _Rationale: this leads to more readable code, and it makes it easier to + evolve an API over time by adding keywords without having to worry about + keyword order._ + +3. For functions that have a single positional array parameter, that parameter + is called `x`. For functions that have multiple array parameters, those + parameters are called `xi` with `i = 1, 2, ...` (i.e., `x1`, `x2`). + +4. Type annotations are left out of the signatures themselves for readability; + they are added to the descriptions of individual parameters however. In code + which aims to adhere to the standard, adding type annotations is strongly + recommended. + +A function signature and description will look like: + +``` +funcname(x1, x2, /, *, key1=-1, key2=None) + + Parameters + + x1 : array + description + x2 : array + description + key1 : int + description + key2 : Optional[str] + description + + Returns + + out : array + description +``` + +Method signatures will follow the same conventions and, modulo the addition of +`self`. diff --git a/spec/API_specification/index.rst b/spec/API_specification/index.rst index ae8246799..f20f916fe 100644 --- a/spec/API_specification/index.rst +++ b/spec/API_specification/index.rst @@ -5,6 +5,7 @@ API specification :caption: API specification :maxdepth: 1 + function_and_method_signatures array_object indexing data_types diff --git a/spec/_static/images/dependency_assumption_diagram.png b/spec/_static/images/dependency_assumption_diagram.png new file mode 100644 index 000000000..f77f11f45 Binary files /dev/null and b/spec/_static/images/dependency_assumption_diagram.png differ diff --git a/spec/assumptions.md b/spec/assumptions.md index b7157e67d..2e5f6f07d 100644 --- a/spec/assumptions.md +++ b/spec/assumptions.md @@ -1,15 +1,74 @@ # Assumptions -## Hardware environments +## Hardware and software environments +No assumptions on a specific hardware environment are made. It must be possible +to create an array library adhering to this standard that runs (efficiently) on +a variety of different hardware: CPUs with different architectures, GPUs, +distributed systems and TPUs and other emerging accelerators. +The same applies to software environments: it must be possible to create an +array library adhering to this standard that runs efficiently independent of +what compilers, build-time or run-time execution environment, or distribution +and install method is employed. Parallel execution, JIT compilation, and +delayed (lazy) evaluation must all be possible. -## Software environments - +The variety of hardware and software environments puts _constraints_ on choices +made in the API standard. For example, JIT compilers may require output dtypes +of functions to be predictable from input dtypes only rather than input values. ## Dependencies +The only dependency that's assumed in this standard is that on Python itself. +Python >= 3.8 is assumed, motivated by the use of positional-only parameters +(see [function and method signatures](API_specification/function_and_method_signatures.md)). + +Importantly, array libraries are not assumed to be aware of each other, or of +a common array-specific layer. The [use cases](use_cases.md) do not require +such a dependency, and building and evolving an array library is easier without +such a coupling. Facilitation support of multiple array types in downstream +libraries is an important use case however, the assumed dependency structure +for that is: + +![dependency assumptions diagram](_static/images/dependency_assumption_diagram.png) + +Array libraries may know how to interoperate with each other, for example by +constructing their own array type from that of another library or by shared +memory use of an array (see [Data interchange mechanisms](design_topics/data_interchange.md)). +This can be done without a dependency though - only adherence to a protocol is +enough. + +Array-consuming libraries will have to depend on one or more array libraries. +That could be a "soft dependency" though, meaning retrieving an array library +namespace from array instances that are passed in, but not explicitly doing +`import arraylib_name`. + + +## Backwards compatibility + +The assumption made during creation of this standard is that libraries are +constrained by backwards compatibility guarantees to their users, and are +likely unwilling to make significant backwards-incompatible changes for the +purpose of conforming to this standard. Therefore it is assumed that the +standard will be made available in a new namespace within each library, or the +library will provide a way to retrieve a module or module-like object that +adheres to this standard. See [How to adopt this API](purpose_and_scope.html#how-to-adopt-this-api) +for more details. + + +## Production code & interactive use +It is assumed that the primary use case is writing production code, for example +in array-consuming libraries. As a consequence, making it easy to ensure that +code is written as intended and has unambiguous semantics is preferred - and +clear exceptions must be raised otherwise. -## Interactive use & production code +It is also assumed that this does not significantly detract from the +interactive user experience. However, in case existing libraries differ in +behavior, the more strict version of that behavior is typically preferred. A +good example is array inputs to functions - while NumPy accepts lists, tuples, +generators, and anything else that could be turned into an array, most other +libraries only accept their own array types. This standard follows the latter choice. +It is likely always possible to put a thin "interactive use convenience layer" +on top of a more strict behavior.