Currently, functions of this package require passing a standard-compatible namespace as xp=xp. This works fine, but there have been suggestions that it might be nice to avoid this requirement. There are at least a few ways we could go about this:
(1) xpx.bind_namespace
Usage:
importarray_api_strictasxpx
...
xp=array_namespace(x)
xpx=xpx.bind_namespace(xp)
x=xpx.atleast_nd(x, ndim=2)
y=xp.sum(x)
z=xpx.some_func(y)
A potential implementation:
extra_funcs= {'atleast_nd': atleast_nd, ...}
defbind_namespace(xp: ModuleType) ->ModuleType:
classBoundNamespace:
def__getattr__(self, name: str):
ifnameinextra_funcs:
returnfunctools.partial(extra_funcs[name], xp=xp)
else:
returnAttributeError(...)
returnBoundNamespace(xp)I like this idea. If we encounter use cases where a library wants to use multiple xpx functions in the same local scope and finds the xp=xp pattern too cumbersome, I think we should add this. I think we can leave it out for now until that situation arises.
(2) xpx.extra_namespace
Usage:
importarray_api_strictasxpx
...
xp=array_namespace(x)
xpx=xpx.extra_namespace(xp)
x=xpx.atleast_nd(x, ndim=2)
y=xpx.sum(x) # XXX: xpx instead of xpz=xpx.some_func(y)
A potential implementation:
extra_funcs= {'atleast_nd': atleast_nd, ...}
defextra_namespace(xp: ModuleType) ->ModuleType:
classExtraNamespace:
def__getattr__(self, name: str):
ifnameinextra_funcs:
returnfunctools.partial(extra_funcs[name], xp=xp)
else:
returngetattr(xp, name) # XXX: delegate to xp instead of errorreturnExtraNamespace(xp)I would not want to add this yet. I think we should keep separation between the standard namespace and the 'extra' namespace, at least until this library matures.
(3) Use array_api_compat.array_namespace internally
This would provide the most flexible API and be the least LOC to use. One could use xpx functions on standard-incompatible arrays, and let array-api-compat handle the compatibility, without having to pass an xp argument.
We don't yet have a use case where it is clearly beneficial to be able to pass standard-incompatible arrays. Consumer libraries using array-api-extra would already be computing with standard-compatible arrays internally. I don't see the need to support the following use case:
importtorchimportarray_api_strictasxpx
...
x=torch.asarray([1, 2, 3])
xpx.some_func(x) # workstorch.some_standard_func(x) # does not work
Another complication is that consumer libraries like SciPy wrap array_namespace to provide custom behaviour for scalars and other types. We would want the internal array_namespace to be the consumer library's wrapped version rather than the base one from array-api-compat.
I'm also not sure that the 1 LOC save over option (1) of this post for standard-compatible arrays is worth introducing a dependency on array-api-compat.
Overall, this would complicate things a lot with situations of co-vendoring array-api-compat and array-api-extra, which is the primary use-case for the library right now. This might be a better idea in the future if a need for handling standard-incompatible arrays arises (for example, if one wants to use functions from xpx with just a single library).
Currently, functions of this package require passing a standard-compatible namespace as
xp=xp. This works fine, but there have been suggestions that it might be nice to avoid this requirement. There are at least a few ways we could go about this:(1)
xpx.bind_namespaceUsage:
A potential implementation:
I like this idea. If we encounter use cases where a library wants to use multiple
xpxfunctions in the same local scope and finds thexp=xppattern too cumbersome, I think we should add this. I think we can leave it out for now until that situation arises.(2)
xpx.extra_namespaceUsage:
A potential implementation:
I would not want to add this yet. I think we should keep separation between the standard namespace and the 'extra' namespace, at least until this library matures.
(3) Use
array_api_compat.array_namespaceinternallyThis would provide the most flexible API and be the least LOC to use. One could use
xpxfunctions on standard-incompatible arrays, and let array-api-compat handle the compatibility, without having to pass anxpargument.We don't yet have a use case where it is clearly beneficial to be able to pass standard-incompatible arrays. Consumer libraries using array-api-extra would already be computing with standard-compatible arrays internally. I don't see the need to support the following use case:
Another complication is that consumer libraries like SciPy wrap
array_namespaceto provide custom behaviour for scalars and other types. We would want the internalarray_namespaceto be the consumer library's wrapped version rather than the base one from array-api-compat.I'm also not sure that the 1 LOC save over option (1) of this post for standard-compatible arrays is worth introducing a dependency on array-api-compat.
Overall, this would complicate things a lot with situations of co-vendoring array-api-compat and array-api-extra, which is the primary use-case for the library right now. This might be a better idea in the future if a need for handling standard-incompatible arrays arises (for example, if one wants to use functions from
xpxwith just a single library).