I would like to define a unlines
function which works which any Sequence whose elements conform to the StringProtocol; this is my attempt:
func unlines<S: StringProtocol>(_ xs: Sequence<S>) -> S {
return xs.joined(separator: "\n")
}
Error: Use of protocol 'Sequence' as a type must be written 'any Sequence'
A version defined for a concrete type does work:
func unlines(_ xs: [String]) -> String {
return xs.joined(separator: "\n")
}
but can only be applied with list of String.
How can I develop a general definition ?
EDIT:
For example, I would like to apply it to the following value:
["Hello", "World"].lazy.map { $0.lowercased() }
CodePudding user response:
joined
returns a String so you need to change the return type and use any Sequence
func unlines<S: StringProtocol>(_ xs: any Sequence<S>) -> String {
return xs.joined(separator: "\n")
}
This then works both with String and Substring
String example:
let result = unlines(["A", "B", "C"])
Substring example:
let result = unlines("A-B-C".split(separator: "-"))
both returns
A
B
C
CodePudding user response:
In Swift, you'd typically use a protocol extension to define instance functions that should operate on an instance, rather than using free functions that take a first argument.
Here's how that might work:
extension Sequence where Element: StringProtocol {
// FIXME: This is a pretty Haskelly, non-Swifty
func unlines() -> String {
joined(separator: "\n")
}
}
let input = ["Hello", "World"]
.lazy
.map { $0.lowercased() }
.unlines()
print(input)
// Prints:
// hello
// world