Pattern Matching is a check to see if a string or data structure contains a certain element. In Swift, Pattern Matching is done via case let
statements with different types of data structures.
Enums
Pattern Matching is extremely effective when used with enums:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | enum State <span class="token operator"><</span> Data <span class="token operator">></span> <span class="token punctuation">{</span> case loading case loaded <span class="token punctuation">(</span> Data <span class="token punctuation">)</span> case failed <span class="token punctuation">(</span> Error <span class="token punctuation">)</span> <span class="token punctuation">}</span> switch state <span class="token punctuation">{</span> case <span class="token punctuation">.</span> loading <span class="token punctuation">:</span> renderLoading <span class="token punctuation">(</span> <span class="token punctuation">)</span> case let <span class="token punctuation">.</span> loaded <span class="token punctuation">(</span> shows <span class="token punctuation">)</span> where shows <span class="token punctuation">.</span> isEmpty <span class="token punctuation">:</span> renderEmptyView <span class="token punctuation">(</span> <span class="token punctuation">)</span> case let <span class="token punctuation">.</span> loaded <span class="token punctuation">(</span> shows <span class="token punctuation">)</span> <span class="token punctuation">:</span> render <span class="token punctuation">(</span> shows <span class="token punctuation">)</span> case let <span class="token punctuation">.</span> failed <span class="token punctuation">(</span> error <span class="token punctuation">)</span> <span class="token punctuation">:</span> render <span class="token punctuation">(</span> error <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
When using the switch
statement for enums with associated values, the case let
statement can be used to test a case and assign a value to a variable. Moreover, you can filter the attached value through the where
statement.
Optionals
The nature of Optional in Swift is that enum has two cases, so using case let for optional is the same as for enum.
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">let</span> value <span class="token punctuation">:</span> <span class="token builtin">Int</span> <span class="token operator">?</span> <span class="token operator">=</span> <span class="token number">10</span> <span class="token keyword">switch</span> value <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token keyword">let</span> value <span class="token operator">?</span> <span class="token keyword">where</span> value <span class="token operator">></span> <span class="token number">10</span> <span class="token punctuation">:</span> <span class="token function">print</span> <span class="token punctuation">(</span> <span class="token string">"greater than ten"</span> <span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token keyword">let</span> <span class="token punctuation">.</span> <span class="token function">some</span> <span class="token punctuation">(</span> value <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token function">print</span> <span class="token punctuation">(</span> value <span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token punctuation">.</span> <span class="token keyword">none</span> <span class="token punctuation">:</span> <span class="token function">print</span> <span class="token punctuation">(</span> <span class="token string">"none"</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
In the case of .some(value)
, could it be written as a value?
.
Tuples
Pattern Matching can also be used effectively on tuple data structures.
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">let</span> auth <span class="token operator">=</span> <span class="token punctuation">(</span> username <span class="token punctuation">:</span> <span class="token string">"majid"</span> <span class="token punctuation">,</span> password <span class="token punctuation">:</span> <span class="token string">"veryStrongPassword"</span> <span class="token punctuation">)</span> <span class="token keyword">switch</span> auth <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token punctuation">(</span> <span class="token string">"admin"</span> <span class="token punctuation">,</span> <span class="token string">"admin"</span> <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token function">renderAdmin</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token keyword">let</span> <span class="token punctuation">(</span> <span class="token number">_</span> <span class="token punctuation">,</span> password <span class="token punctuation">)</span> <span class="token keyword">where</span> password <span class="token punctuation">.</span> <span class="token builtin">count</span> <span class="token operator"><</span> <span class="token number">6</span> <span class="token punctuation">:</span> <span class="token function">renderShortPasswordMessage</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token keyword">let</span> <span class="token punctuation">(</span> username <span class="token punctuation">,</span> password <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token function">renderUserProfile</span> <span class="token punctuation">(</span> username <span class="token punctuation">,</span> password <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Conditional statements
case let
can also be used in conjunction with conditional statements:
1 2 3 4 | <span class="token keyword">if</span> <span class="token keyword">case</span> <span class="token keyword">let</span> <span class="token punctuation">.</span> <span class="token function">loaded</span> <span class="token punctuation">(</span> shows <span class="token punctuation">)</span> <span class="token operator">=</span> state <span class="token punctuation">,</span> shows <span class="token punctuation">.</span> isEmpty <span class="token punctuation">{</span> <span class="token function">renderEmptyView</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
, or:
1 2 3 4 | guard <span class="token keyword">case</span> <span class="token keyword">let</span> <span class="token punctuation">.</span> <span class="token function">loaded</span> <span class="token punctuation">(</span> shows <span class="token punctuation">)</span> <span class="token operator">=</span> state <span class="token punctuation">,</span> shows <span class="token punctuation">.</span> isEmpty <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">// Do something here</span> <span class="token punctuation">}</span> |
Iterative statement
In addition to use in branching structures, case let
can be used in loops as well:
1 2 3 4 5 | <span class="token keyword">let</span> stateHistory <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token builtin">State</span> <span class="token operator"><</span> <span class="token punctuation">[</span> <span class="token builtin">Show</span> <span class="token punctuation">]</span> <span class="token operator">></span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">.</span> <span class="token function">loaded</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token punctuation">.</span> loading <span class="token punctuation">]</span> <span class="token keyword">for</span> <span class="token keyword">case</span> <span class="token keyword">let</span> <span class="token punctuation">.</span> <span class="token function">loaded</span> <span class="token punctuation">(</span> shows <span class="token punctuation">)</span> <span class="token keyword">in</span> stateHistory <span class="token keyword">where</span> shows <span class="token punctuation">.</span> <span class="token builtin">count</span> <span class="token operator">></span> <span class="token number">2</span> <span class="token punctuation">{</span> <span class="token comment">// Do something here</span> <span class="token punctuation">}</span> |
References
https://swiftwithmajid.com/2019/02/06/pattern-matching-with-case-let/