Python String Slices in PHP
This past weekend, I decided I wanted to bring one of my favourite shortcuts
in Python to PHP strings: its slice notation. Limiting myself to userland
code, there wasn’t much I could do to replicate the syntax. Implementing the
ArrayAccess interface would allow me to overload array dimensions in a
class, though I’d be stuck parsing string offsets for the necessary arguments.
My first attempt, writing only from how I remembered using the slice notation, got me half way there. It handled start and stop well in the case of positive steps, but failed to handle a variety of negative steps. It was a simple mistake, as I wasn’t handling all possible adjustments to the slice boundaries. After looking at CPython’s implementation, I was able to spot where I went wrong and hopefully achieve an implementation that mimics Python’s own behaviour. Here’s a small preview of its use:
1 2 3 4 5 6 7 8
How did I test it? Aside from the unit tests, I decided to write a quick fixture generator so that I could compare a large number of input, and their output, between CPython and my PHP code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
The code above generates a CSV with rows having the format “[Args],Result”, e.g. “[:-6:-3],cs”. I chose the range of arguments to test based on how boundaries are adjusted given the lengths of the string. Afterward, it was just a matter of writing a functional test that would compare the results:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
I’m fortunate that despite the size of the test space (> 4600 fixture entries), it’s only testing string operations, and so the whole suite runs in ~0.06s on my MacBook Air.
For anyone interested, I’ve uploaded the library to GitHub. It’s a single class, SliceableStringy, that inherits from Stringy. It can be found at: https://github.com/danielstjules/SliceableStringy