{"id":24371,"date":"2019-02-20T17:13:06","date_gmt":"2019-02-20T22:13:06","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=24371"},"modified":"2019-02-20T17:13:06","modified_gmt":"2019-02-20T22:13:06","slug":"the-curiously-recursive-inlinable-switch-pattern-crisp","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2019\/02\/20\/the-curiously-recursive-inlinable-switch-pattern-crisp\/","title":{"rendered":"The Curiously Recursive Inlinable Switch Pattern (CRISP)"},"content":{"rendered":"<p><a href=\"https:\/\/github.com\/apple\/swift\/blob\/master\/docs\/StandardLibraryProgrammersManual.md#the-curiously-recursive-inlinable-switch-pattern-crisp\">Jordan Rose<\/a> (via <a href=\"https:\/\/twitter.com\/UINT_MIN\/status\/1097984505250365440\">tweet<\/a>):<\/p>\n<blockquote cite=\"https:\/\/github.com\/apple\/swift\/blob\/master\/docs\/StandardLibraryProgrammersManual.md#the-curiously-recursive-inlinable-switch-pattern-crisp\"><p>When inlinable code switches over a non-frozen enum, it has to handle possible future cases (since it will be inlined into a module outside the standard library). You can see this in action with the implementation of <code>round(_:)<\/code> in FloatingPointTypes.swift.gyb, which takes a FloatingPointRoundingRule. It looks something like this:<\/p>\n<p>[&#8230;]<\/p>\n<p>Making <code>round(_:)<\/code> inlinable but still have a default case is an attempt to get the best of both worlds: if the rounding rule is known at compile time, the call will compile down to a single instruction in optimized builds; and if it dynamically turns out to be a new kind of rounding rule added in Swift 25 (e.g. <code>.towardFortyTwo<\/code>), there&rsquo;s a fallback function, <code>_roundSlowPath(_:)<\/code>, that can handle it.<\/p><\/blockquote>\n<p>It looks like the function is calling itself, but it&rsquo;s actually calling a future version of itself that is guaranteed not to recurse.<\/p>\n\n<p>Previously: <a href=\"https:\/\/mjtsai.com\/blog\/2017\/09\/22\/swift-proposal-non-exhaustive-enums\/\">Swift Proposal: Non-Exhaustive Enums<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Jordan Rose (via tweet): When inlinable code switches over a non-frozen enum, it has to handle possible future cases (since it will be inlined into a module outside the standard library). You can see this in action with the implementation of round(_:) in FloatingPointTypes.swift.gyb, which takes a FloatingPointRoundingRule. It looks something like this: [&#8230;] Making [&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-02-20T22:13:09Z","apple_news_api_id":"73ae3a53-048a-4289-bdc3-28011d53a15b","apple_news_api_modified_at":"2019-02-20T22:13:09Z","apple_news_api_revision":"AAAAAAAAAAD\/\/\/\/\/\/\/\/\/\/w==","apple_news_api_share_url":"https:\/\/apple.news\/Ac646UwSKQom9wygBHVOhWw","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":[669,46,138,71,901],"class_list":["post-24371","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-floating-point","tag-languagedesign","tag-optimization","tag-programming","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/24371","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=24371"}],"version-history":[{"count":1,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/24371\/revisions"}],"predecessor-version":[{"id":24372,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/24371\/revisions\/24372"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=24371"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=24371"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=24371"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}