- Status: Accepted
- Implementation status: Done
Often one wants to write a single piece of code that can operate on several different types. C++ accomplishes this with templates, which are powerful but add an enormous level of complexity to the language. There is also the issue of requiring implementations to be in header files and re-compiled for every computational unit. Java generics can only operate on boxed values, which is unsuitable for scientific computation (though one does get type safety vs. typing everything as object). This CEP is an alternative to full parameterized types for the common usecase where the set of needed types is small and fixed ahead of time.
There will be a new "fused type" which represents an implicit interface, the intersection of its component types. E.g.
ctypedef cython.fused_type(float, double, long double) floating
Arithmetic can be done iff all specifications can be done, common attributes accessed.
One could write
cdef floating f(floating x, floating y): cdef floating tmp = ... if typeof(x) is double: # or floating is double or isinstance(x, double) [double specific code, methods/attributes specific to double can be accessed here] return x + y
which would get expanded out into 2 specializations. Calling f(1.0f, 2) or f(1.0f, 2.0) would dispatch to the float and double specification respectively. f[double] would obtain an exact specialization (in both Cython and Python space).
cdef floating f(floating x, integral y): cdef floating tmp = ... return x + y
would create 4 specializations.
One could also write
cdef class A: cdef floating x cdef __init__(self): self.x = 1
Again, A[double] would produce a specialization, and could be used for instantiation. The specialization could be inferred, if possible, from constructor arguments. If there are multiple fused types, we may require the declaration to be cdef class A[floating, integral] to force an ordering for access purposes.
It may make sense to provide some special types.
- floating -- float, double, long double
- integral -- all int types
- numeric -- all numeric types
- cdef complex floating supported if floating is a numeric type
- What do do with external types? Switch statement to the right dispatch based on their size (the way python object conversion is done)?
- signed/unsigned integral types?