Skip to content

Instantly share code, notes, and snippets.

@ole
Last active November 7, 2018 14:18
Show Gist options
  • Save ole/1e3f1b3d2f8ca1f5b79de262f74678d0 to your computer and use it in GitHub Desktop.
Save ole/1e3f1b3d2f8ca1f5b79de262f74678d0 to your computer and use it in GitHub Desktop.
Swift challenge: Sequence.headAndTail. Context: https://twitter.com/olebegemann/status/1059923129345196032
// Challenge: Fill out this extension
//
// I have a solution for this return type:
//
// var headAndTail: (head: Element, tail: AnySequence<Element>)?
//
// I don't think it can be done with tail: SubSequence.
extension Sequence {
/// Destructures `self` into the first element (head) and the rest (tail).
/// Returns `nil` if the sequence is empty.
var headAndTail: (head: Element, tail: SubSequence)? {
// ,,,
}
}
// Test case 1:
assert([1, 2, 3].headAndTail! == (1, [2, 3]))
// Test case 2 (a consuming sequence):
var i = 1
let seq = AnySequence {
AnyIterator { () -> Int? in
defer { i += 1 }
return i
}
}
let (head, tail) = seq.headAndTail!
assert(head == 1)
assert(Array(tail.prefix(3)) == [2,3,4])
// Printing the output for debugging
// Note that because the sequence is self-consuming, just commenting out the last line
// will always print something else than 2 3 4. You must also comment the related
// assertion above.
print(head) // should output 1
//tail.prefix(3).forEach { print($0) } // should output 2 3 4
@burhanuddin353
Copy link

extension Sequence {

    var headAndTail: (head: Element, tail: SubSequence)? {
 
        let count = reduce(0) { c, element in c + 1 }
        guard count > 0 else { return nil }
        return (head: compactMap({$0}).first!, tail: dropFirst())
    }
}

@ole
Copy link
Author

ole commented Nov 7, 2018

@burhanuddin353 That code goes into an infinite loop when executing the second test case because your code is trying to count the number of elements in an infinite sequence. It also wouldn't work with self-consuming sequences because the calls to reduce and compactMap would consume the entire sequence.

@ole
Copy link
Author

ole commented Nov 7, 2018

Update: @dennisvennink found a solution using drop(while:) to "catch" the first element before it gets lost: https://gist.github.com/dennisvennink/e8b1921916d3c2f90ab52f47291145ef

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment