No, I don’t think syntax can perfectly signal the runtime complexity of an API access. But I do think there is a general assumption about what different access patterns entail:
- subscript: generally O(1), sometimes O(log(n))
- property: generally O(1) or O(log(n)), sometimes O(n)
- function: no guarantee, might be O(1), might be much more expensive
There are exceptions, but I would not use a property for something that takes O(n2) time or a subscript that is O(n).
O(n) for a property access already feels like a stretch. This causes confusion for Swift programmers that assume string.count
is O(1) – me, for quite some time – and read the property repeatedly instead of caching the value. Maybe the compiler can optimize that, but I would not want to rely on such optimizations.
I am sure that if it were spelled string.count()
, people would be more hesitant to make the call over and over again and instead read the value once and then use the cached value.
Similarly, subscript notation is near constant-time in almost every language I can think of, including Swift. A verbose subscript label might help, but finding a good name is no easy task. I feel like almost everyone can agree that array access with optional return value (array[safe: index]
or array[optional: …]
or any of many other proposed names) would a great feature, but the lack of consensus on the label name has prevented the feature from landing in the language.
I would be somewhat OK with something like
string.character(atOffset: 5)
string.substring(from: 3 ..< 7)
but it’s not much of an improvement over what we have already (the family of collection methods):
string.dropFirst(4).first
string.dropFirst(9).prefix(12)
I mostly think that if you need integer indices into a string, you should probably reconsider if that is the best solution to your string processing task. For example, when parsing some text file, most formats are not based on Unicode extended grapheme clusters, so if some spec tells you to “skip four characters and then read until the next space character”, that spec is probably talking about bytes or UTF-16 units and about the ASCII space and not the Unicode space character property.
And for those times where integer indices into strings are the best solution, you can still do it with a single line of code in Swift.
I do want to acknowledge that that name “dropFirst
” does not help it’s case; its a bad name that needs some time to get used to if you are not familiar with this style of programming. It sounds so much more dangerous that what it actually does.