I'm currently experimenting with tensor slicing syntax in Swift, to see what is possible. I've run into limitations, and I'd like to get advice and/or report feedback for possible evolution of the language. Please let me know if this has already been discussed.
From Python/Numpy (but it shares a lot with preexisting math packages like Matlab/Scilab/Octave and others I haven't experienced so far):
tensor[:,:,1:7] // returns a 3D tensor (full ranges on first/second axis, range on last axis)
tensor[:,:,1::2] // returns a 3D tensor (same, but stride of 2 on last axis)
tensor[:,:,1:5:2] // returns a 3D tensor (another)
tensor[1,:,4:] // returns a 2D tensor (picks first axis & remove it, + range on last axis)
tensor[np.newaxis,:,:,:] // returns a 4D tensor (inserts a new axis)
I implemented all these behaviors in CeedNumerics as a test bed, it's not too bad, but I still can't get a syntax that is as legible as Python's.
tensor[n.all,n.all,1~7]
tensor[n.all,n.all,1~~2]
tensor[n.all,n.all,1~5~2]
tensor[1,n.all,4~]
tensor[n.newaxis,n.all,n.all,n.all]
Had to replace the :
with ~
(colon can't be used as it is reserved). I used the same enum/operator trick that Swift uses for the UnboundedRange (...) that can be used both standalone or with arguments. But this has some limitations:
- can't make it conform to a protocol, and thus I have to write a number of specific subscripts with all combinations (
~
as 1st argument, as 2nd, and both for a 2D type) - can't use it when arguments is of type
[Any]
(which I need, because standalone~
can't conform to a protocol.
Note that standalone ~
can be used in place of n.all in the case of matrices, as [Any]
subscript can be skipped altogether.
matrix[~,1]
tensor[n.all, 1] // n.all must be used instead of ~
I'd be interested in these specific points:
- is there a chance that the colon syntax for tensor slicing (
start:end:step
, + stand alone/unary/binary variants), that is generally well accepted and used for math programming, becomes available in Swift? - if not, is there hope to see improvements (removal of the UnboundedRange, or at least allow protocol conformance) to make the proposed workaround work better (and avoid the n.all constant)?
- Any additional feedback or discussion about the long-term plan about how to better express math stuff in Swift, or short-term tricks that can be used right away would also be appreciated.
Thank you.