Skip to content

Instantly share code, notes, and snippets.

@milseman
Created February 28, 2018 20:26
Show Gist options
  • Save milseman/f9b5528345db3a36bbdd138af52c5cda to your computer and use it in GitHub Desktop.
Save milseman/f9b5528345db3a36bbdd138af52c5cda to your computer and use it in GitHub Desktop.
Playground for Self-sliced Collections: eat/seek/peek
// Eat/seek/peek
extension Collection where SubSequence == Self, Element: Equatable {
mutating func eat() -> Element {
defer { self = self.dropFirst() }
return peek()
}
mutating func eat(_ n: Int) -> SubSequence {
let (pre, rest) = self.seek(n)
defer { self = rest }
return pre
}
mutating func eat(asserting on: Element) -> Element {
let e = eat()
assert(on == e)
return e
}
mutating func eat(until f: (Element) -> Bool) -> SubSequence {
let (pre, rest) = self.seek(until: f)
defer { self = rest }
return pre
}
// ... eat(while:) eat(anyOf:) eat(manyOf:) eat(until:) ...
func peek() -> Element {
return self.first!
}
func peek(_ n: Int) -> Element {
assert(n > 0 && self.count >= n)
return self.dropFirst(n).peek()
}
func seek(_ n: Int) -> (prefix: SubSequence, rest: SubSequence) {
return (self.prefix(n), self.dropFirst(n))
}
func seek(until f: (Element) -> Bool) -> (prefix: SubSequence, rest: SubSequence) {
guard let point = self.index(where: f) else {
return (self[...], self[endIndex...])
}
return (self[..<point], self[point...])
}
// ... seek(until: Element), seek(through:), seek(until: Set<Element>), seek(through: Set<Element>) ...
}
let string = "a𝔹cdề\u{301}\u{302}f𝔾h⒤jklmnoᕉ𝙌Ⓡş"
var scanner = string[...]
scanner.eat(/*om nom nom*/) // a
scanner // bcdefghijklmnoᕉ𝙌Ⓡş
scanner.eat(3) // 𝔹cd
scanner.eat(asserting: "\u{0065}\u{0302}\u{0300}\u{0301}\u{0302}") // ề́̂
scanner.peek() // f
scanner.peek(3) // ⒤
scanner.seek(3) // (prefix: f𝔾h, rest: ⒤jklmnoᕉ𝙌Ⓡş)
let (pre, rest) = scanner.seek(until: { $0 == "o" }) // (prefix: f𝔾h, rest: ⒤jklmnoᕉ𝙌Ⓡş)
pre // f𝔾h⒤jklmn
rest // oᕉ𝙌Ⓡş
var theRestInCodeUnits = Array(scanner.utf8)[...]
theRestInCodeUnits.eat(5) // [102, 240, 157, 148, 190]
theRestInCodeUnits // ... the rest ...
let nom = scanner.eat(until: { $0 == "o" })
nom // f𝔾h⒤jklmn
scanner // oᕉ𝙌Ⓡş
print("done")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment