Earlier today I was talking with a colleague about extracting a substring of a string given the start and end indices. He showed me an implementation in Javascript and I wrote one in Java and then looked at the Java 8 implementation which I’ve pasted below.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public String substring(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } if (endIndex > value.length) { throw new StringIndexOutOfBoundsException(endIndex); } int subLen = endIndex - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } return ((beginIndex == 0) && (endIndex == value.length)) ? this: new String(value, beginIndex, subLen); } |
If we reformatted this we’d have 6 lines of code.
Now for some Haskell… What is it we do when extracting a substring? For me, I think of it as taking the string, dropping the chars up to the start index and then from that getting chars up to the end index and then forgetting about everything after that. Here it is in Haskell generalised to work on arbitrary lists and not just strings.
1 2 |
substr :: Int -> Int -> [a] -> [a] substr s e xs = take e (drop s xs) |
I think that is beautiful in its simplicity and elegance.
Corner cases of index values are handled gracefully and the same function will work on any type – Strings, numbers…
Here’s some ‘bad index’ examples:
1 2 3 4 5 6 7 8 |
λ-> substr 1 20 "abcdefgh" "bcdefgh" *Main λ-> substr (-10) 20 "abcdefgh" "abcdefgh" *Main λ-> substr 100 200 "abcdefgh" "" |
And on a list of Int
1 2 |
λ-> substr 2 4 [1,2,3,4,5] [3,4,5] |
Short and Sweet!
Thanks for reading…