{"id":23823,"date":"2019-01-01T15:41:16","date_gmt":"2019-01-01T20:41:16","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=23823"},"modified":"2019-01-01T15:41:34","modified_gmt":"2019-01-01T20:41:34","slug":"splitting-a-swift-sequence-into-head-and-tail","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2019\/01\/01\/splitting-a-swift-sequence-into-head-and-tail\/","title":{"rendered":"Splitting a Swift Sequence Into Head and Tail"},"content":{"rendered":"<p><a href=\"https:\/\/oleb.net\/2018\/sequence-head-tail\/\">Ole Begemann<\/a>:<\/p>\n<blockquote cite=\"https:\/\/oleb.net\/2018\/sequence-head-tail\/\">\n<p>One possible solution is to <a href=\"https:\/\/developer.apple.com\/documentation\/swift\/sequence\/2885155-makeiterator\">create an iterator<\/a> to read in the first element, and then wrap the current iterator state in a new <a href=\"https:\/\/developer.apple.com\/documentation\/swift\/anysequence\"><code>AnySequence<\/code><\/a> instance[&#8230;] This code works, but it&rsquo;s not a nice generic solution, especially for types that also conform to <code>Collection<\/code>. Wrapping the tail in an <code>AnySequence<\/code> is <a href=\"https:\/\/github.com\/apple\/swift-evolution\/blob\/master\/proposals\/0234-remove-sequence-subsequence.md#type-erasure-performance\">a big performance killer<\/a>, and you can&rsquo;t use the affordances of a collection&rsquo;s proper <a href=\"https:\/\/developer.apple.com\/documentation\/swift\/sequence\/1641117-subsequence#\"><code>SubSequence<\/code><\/a> type.<\/p>\n<p>[&#8230;]<\/p>\n<p>Dennis&rsquo;s trick is to call <a href=\"https:\/\/developer.apple.com\/documentation\/swift\/sequence\/2965501-drop\"><code>Sequence.drop(while:)<\/code><\/a>, which preserves the <code>SubSequence<\/code> type for the tail, and then &ldquo;catch&rdquo; the first element inside the <code>drop(while:)<\/code> predicate closure using a captured local variable. Nicely done!<\/p>\n<p>[&#8230;]<\/p>\n<p>The code above targets Swift 4.2. It will break in Swift 5 because sequences will no longer have an associated <code>SubSequence<\/code> type, only collections (<a href=\"https:\/\/github.com\/apple\/swift-evolution\/blob\/master\/proposals\/0234-remove-sequence-subsequence.md\">Swift Evolution proposal SE-0234<\/a>).<\/p>\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Ole Begemann: One possible solution is to create an iterator to read in the first element, and then wrap the current iterator state in a new AnySequence instance[&#8230;] This code works, but it&rsquo;s not a nice generic solution, especially for types that also conform to Collection. Wrapping the tail in an AnySequence is a big [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2019-01-01T20:41:17Z","apple_news_api_id":"9a8b8fef-f5e7-4a24-891f-3b3035892b9f","apple_news_api_modified_at":"2019-01-01T20:41:38Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAA==","apple_news_api_share_url":"https:\/\/apple.news\/AmouP7_XnSiSJHzswNYkrnw","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[31,1610,30,1609,71,901],"class_list":["post-23823","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-ios","tag-ios-12","tag-mac","tag-macos-10-14","tag-programming","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/23823","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=23823"}],"version-history":[{"count":1,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/23823\/revisions"}],"predecessor-version":[{"id":23824,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/23823\/revisions\/23824"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=23823"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=23823"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=23823"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}