Reputation: 77641
I'd like to get a substring of a string that is just the first N characters. (10, for example).
But the string is the generated output of a function.
I'd like to do it like this...
let string = someInputString
.someGeneratorFunctionThatReturnsAString()
.substring(to: 10)
But I can't do this. Because the index in the substring function needs the string itself to determine where the 10th character is.
Upvotes: 2
Views: 85
Reputation: 1367
See Gunhan's answer to question 2.
For question 1:
Long Answer: Basically, in Swift, the Collection protocol (which types like Array and String adopt) specifies performance criteria. Most notably, the start and end indices of a collection must be accessible in O(1) time. This goes for subscript access of elements as well (see text under Expected Performance heading on https://developer.apple.com/documentation/swift/collection).
Indices are memory addresses that point to either another reference or value type. For string, the indices point to Character
struct values. While the value of the characters in the strings let x = "hello"
and let y = "hello"
might be the same, the constants x
and y
are different memory addresses and so are the indices that point to their respective Character
struct values. So, you cannot get the substring "llo"
from x
and the substring "llo"
from y
using the same indices... that would make no sense, because the indices you would use would be specific memory addresses to only of those variables.
Architecturally, there are three entities having interplay here:
String |--hasIndicesOfType--> String.Index |--whichPointTo--> Character
(Side note: Here, Index
is an associatedtype
on String
, which is why you see the notation String.Index
if you were to, say, log one of these to the Xcode console).
In a nutshell: the answer to why the function needs the string itself is because indices of a string are memory addresses to characters of the string. String
conforms to Collection
to get O(1) performance on access to String
's elements. Thus, the indices. Because indices are memory addresses, they only work on a given object (reference type) - which is why generic access to characters of a string only work for one string (i.e. you cannot access string A's elements with memory addresses to string B's characters... that doesn't make sense.)
In a super tiny nutshell: because String
conforms to Collection
.
Some helpful tutorial-ish code:
Teleology: Apparent end-goal-reasoning (aka teleological analysis) behind why String
is the way it is in Swift:
Contributors to the language preferred optimizing time complexity over space complexity.
Upvotes: 1
Reputation: 7035
I just maybe understand your question wrong but nevertheless here you can substring easily:
extension String {
func substring(to: Int) -> String? {
return self.substring(to: self.index(self.startIndex, offsetBy: to))
}
}
Upvotes: 3