I would keep the method name in the same vain as the two other String APIs: String.prefix() and String.suffix(). Therefor I would use String.infix() which means “a formative element inserted in a word”.
Current String APIs
func prefix(_ maxLength: Int) -> Substring
func prefix(while predicate: (Character) throws -> Bool) rethrows -> Substring
func suffix(_ maxLength: Int) -> Substring
I propose adding the following APIs to String
func infix(from position: Int, maxLength: Int = Int.max) -> Substring
func infix(from position: Int, while predicate: (Element) throws -> Bool) rethrows -> Substring
Example implementation
/// Companion function to String.prefix() and String.suffix(). It is similar to
/// Basic's Mid() fuction.
///
/// Returns a subsequence, starting from position up to the specified
/// maximum length, containing the middle elements of the collection.
///
/// If the maximum length exceeds the remaing number of elements in the
/// collection, the result contains all the remaining elements in the collection.
///
/// let numbers = [1, 2, 3, 4, 5]
/// print(numbers.infix(from: 2, maxLength: 2))
/// // Prints "[3, 4]"
/// print(numbers.prefix(from: 2, maxLength: 10))
/// // Prints "[3, 4, 5]"
/// print(numbers.prefix(from: 10, maxLength: 2))
/// // Prints ""
/// print(numbers.infix(from: 0))
/// // Prints "[1, 2, 3, 4, 5]"
/// print(numbers.infix(from: 2))
/// // Prints "[3, 4, 5]"
/// print(numbers.infix(from: 10))
/// // Prints ""
///
/// - Parameters:
/// - position: The starting index in the collection. `position` must be
/// greater than or equal to zero.
/// - maxLength: The maximum number of elements to return. `maxLength`
/// must be greater than or equal to zero. The default for `maxLength`
/// is set so the remaining elements of the collection will be returned.
/// - Returns: A subsequence starting from `position` up to `maxLength`
/// elements in the collection.
func infix(from position: Int, maxLength: Int = Int.max) -> Substring {
// if 'position' is beyond the end then set 'start' to 'endIndex'
let start = index(startIndex, offsetBy: numericCast(position), limitedBy: endIndex) ?? endIndex
// if 'start' + 'maxLength' is beyond the end then set end to 'endIndex'
let end = index(start, offsetBy: numericCast(maxLength), limitedBy: endIndex) ?? endIndex
return self[start..<end]
}
/// Returns a subsequence, starting from position and containing the elements
/// until `predicate` returns `false` and skipping the remaining elements.
///
/// - Parameters:
/// - position: The starting index in the collection. `position` must be
/// greater than or equal to zero.
/// - predicate: A closure that takes an element of the sequence as its
/// argument and returns `true` if the element should be included or
/// `false` if it should be excluded. Once the predicate
/// returns `false` it will not be called again.
///
/// - Complexity: O(*n*), where *n* is the length of the collection.
func infix(from position: Int, while predicate: (Element) throws -> Bool) rethrows -> Substring {
// if 'position' is beyond the end then set 'start' to 'endIndex'
let start = index(startIndex, offsetBy: numericCast(position), limitedBy: endIndex) ?? endIndex
var end = start
while try end != endIndex && predicate(self[end]) {
formIndex(after: &end)
}
return self[start..<end]
}