Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link

burhanuddin353 commented Nov 7, 2018

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

This comment has been minimized.

Copy link
Owner 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

This comment has been minimized.

Copy link
Owner 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
You can’t perform that action at this time.