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
~ (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.