After going through the tools that support manipulating basic data types, we continue to look to the group of tools that support creating flexible processing logic for the code depending on the state of the received data and Iterate operations on the data set. And in this article, we will need to test the code of the sub-program
, so interacting with the resulting code we will do with elm reactor
.
1 2 3 | cd Documents && cd learn-elm elm reactor |
Pattern Matching
The first is a logical construct called Pattern Matching
, which is often seen as equivalent to the conditional or branching structure in Imperative
environments. This name has two words and we will take care of the Matching
element first. Purely Declarative
languages call the branching logic structure Matching
because our program will not have sequential statements but parallel definitions instead.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">module</span> <span class="token constant">Tell</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span> <span class="token hvariable">day</span> <span class="token punctuation">)</span> <span class="token hvariable">day</span> <span class="token operator">:</span> <span class="token constant">Int</span> <span class="token operator">-></span> <span class="token constant">String</span> <span class="token hvariable">day</span> <span class="token hvariable">n</span> <span class="token operator">=</span> <span class="token keyword">case</span> <span class="token hvariable">n</span> <span class="token keyword">of</span> <span class="token number">0</span> <span class="token operator">-></span> <span class="token string">"Sunday"</span> <span class="token number">1</span> <span class="token operator">-></span> <span class="token string">"Monday"</span> <span class="token number">2</span> <span class="token operator">-></span> <span class="token string">"Tuesday"</span> <span class="token number">3</span> <span class="token operator">-></span> <span class="token string">"Wednesday"</span> <span class="token number">4</span> <span class="token operator">-></span> <span class="token string">"Thursday"</span> <span class="token number">5</span> <span class="token operator">-></span> <span class="token string">"Friday"</span> <span class="token number">6</span> <span class="token operator">-></span> <span class="token string">"Saturday"</span> _ <span class="token operator">-></span> <span class="token string">"Unknown"</span> |
The above definition of day n
will be read by the compiler
in turn as:
1 2 3 4 5 6 7 8 9 | day 0 = "Sunday" day 1 = "Monday" day 2 = "Tuesday" day 3 = "Wednesday" day 4 = "Thursday" day 5 = "Friday" day 6 = "Saturday" day _ = "Unknown" |
Particularly for the last position, the _
symbol will be read as other values of n
. Now we will modify the main
program and see the results of running the Tell.day
code in the browser.
1 2 3 4 5 6 7 | <span class="token keyword">module</span> <span class="token constant">Main</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span> <span class="token hvariable">main</span> <span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Html <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span> <span class="token operator">..</span> <span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Tell <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span> <span class="token operator">..</span> <span class="token punctuation">)</span> <span class="token hvariable">main</span> <span class="token operator">:</span> <span class="token constant">Html</span> <span class="token hvariable">message</span> <span class="token hvariable">main</span> <span class="token operator">=</span> <span class="token hvariable">Html.text</span> <span class="token punctuation">(</span> <span class="token hvariable">Tell.day</span> <span class="token number">0</span> <span class="token punctuation">)</span> |
http://localhost:8000/src/Main.elm
Ok. so we have a switch..case
syntax that works fine. However, you see, the difference here is that, on the right side of the case
are value
values, not statement statement
. The case..of
syntax we see here, is a form of relative expression that replaces the repeated rewriting of the name of the sub-program
in the definition as explained above. Therefore, people use the word Matching
instead of the word conditional
in the Imperative
environment.
What about
Pattern
?
That word means format – i.e. we will be able to match by the formats of the data, not necessarily specific values. For example, the type name of the received value, or the format that describes the states of the data structures – for example empty List
, 1 element, 2 elements, or more, etc..
1 2 3 4 5 6 7 8 9 | <span class="token keyword">module</span> <span class="token constant">Tell</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span> <span class="token hvariable">any</span> <span class="token punctuation">,</span> <span class="token hvariable">day</span> <span class="token punctuation">)</span> <span class="token hvariable">any</span> <span class="token operator">:</span> <span class="token constant">Maybe</span> <span class="token hvariable">a</span> <span class="token operator">-></span> <span class="token constant">String</span> <span class="token hvariable">any</span> <span class="token hvariable">value</span> <span class="token operator">=</span> <span class="token keyword">case</span> <span class="token hvariable">value</span> <span class="token keyword">of</span> <span class="token constant">Just</span> <span class="token hvariable">a</span> <span class="token operator">-></span> <span class="token string">"Something"</span> <span class="token constant">Nothing</span> <span class="token operator">-></span> <span class="token string">"Nothing"</span> <span class="token comment">-- day : ...</span> |
1 2 3 | <span class="token comment">-- ...</span> <span class="token hvariable">main</span> <span class="token operator">=</span> <span class="token hvariable">Html.text</span> <span class="token punctuation">(</span> <span class="token hvariable">Tell.any</span> <span class="token punctuation">(</span> <span class="token constant">Just</span> <span class="token number">1001</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> |
http://localhost:8000/src/Main.elm
In this case, if we pass in Just.any
a Just
containing any value, the displayed result is also "Something"
. If you pass Tell.any Nothing
, the display result will be the string "Nothing"
. Does that mean that the Tell.any
only interested in what sort of value the value is in Maybe
, not the question of what the value is? Quantitative how much? Or what’s the content?
Let’s continue to write a subroutine to determine the data state of any List
.
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">module</span> <span class="token constant">Tell</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span> <span class="token hvariable">list</span> <span class="token punctuation">,</span> <span class="token hvariable">any</span> <span class="token punctuation">,</span> <span class="token hvariable">day</span> <span class="token punctuation">)</span> <span class="token hvariable">list</span> <span class="token operator">:</span> <span class="token constant">List</span> <span class="token hvariable">a</span> <span class="token operator">-></span> <span class="token constant">String</span> <span class="token hvariable">list</span> <span class="token hvariable">l</span> <span class="token operator">=</span> <span class="token keyword">case</span> <span class="token hvariable">l</span> <span class="token keyword">of</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token operator">-></span> <span class="token string">"Empty"</span> <span class="token punctuation">[</span> <span class="token hvariable">x</span> <span class="token punctuation">]</span> <span class="token operator">-></span> <span class="token string">"Exactly One"</span> <span class="token hvariable">x</span> <span class="token operator">::</span> <span class="token hvariable">xs</span> <span class="token operator">-></span> <span class="token string">"X and other Xs"</span> <span class="token comment">-- any : ...</span> <span class="token comment">-- day : ...</span> |
1 2 3 | <span class="token comment">-- ...</span> <span class="token hvariable">main</span> <span class="token operator">=</span> <span class="token hvariable">Html.text</span> <span class="token punctuation">(</span> <span class="token hvariable">Tell.list</span> <span class="token punctuation">[</span> <span class="token number">0</span> <span class="token punctuation">,</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">,</span> <span class="token number">3</span> <span class="token punctuation">,</span> <span class="token number">4</span> <span class="token punctuation">,</span> <span class="token number">5</span> <span class="token punctuation">,</span> <span class="token number">6</span> <span class="token punctuation">,</span> <span class="token number">7</span> <span class="token punctuation">,</span> <span class="token number">8</span> <span class="token punctuation">,</span> <span class="token number">9</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> |
In the example code, the pattern
in the last case is x::xs
which means when List l
is the result of inserting an element x
into a List xs
containing other values similar to x
. It also means when List l
contains at least 2 or more elements – including X
and other X
.
Is it possible to match at the same
matching
with specific values set inpattern
?
Yes, for sure! If there are a finite number of special values of interest in the processing logic of the code, we can put those values in place of the variables used in the pattern
. Now Elm
will check the appropriateness of the actual data both in terms of pattern
and value at the location of variables.
The pattern
for such List
are already quite flexible. Now let’s try as an example with Tuple
describing the coordinates of points in 3D space –
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token keyword">module</span> <span class="token constant">Tell</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span> <span class="token hvariable">position</span> <span class="token punctuation">,</span> <span class="token hvariable">list</span> <span class="token punctuation">,</span> <span class="token hvariable">any</span> <span class="token punctuation">,</span> <span class="token hvariable">day</span> <span class="token punctuation">)</span> <span class="token hvariable">position</span> <span class="token operator">:</span> <span class="token punctuation">(</span> <span class="token constant">Int</span> <span class="token punctuation">,</span> <span class="token constant">Int</span> <span class="token punctuation">,</span> <span class="token constant">Int</span> <span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token constant">String</span> <span class="token hvariable">position</span> <span class="token hvariable">coordinates</span> <span class="token operator">=</span> <span class="token keyword">case</span> <span class="token hvariable">coordinates</span> <span class="token keyword">of</span> <span class="token punctuation">(</span> <span class="token number">0</span> <span class="token punctuation">,</span> <span class="token number">0</span> <span class="token punctuation">,</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token string">"Root of the Universe"</span> <span class="token punctuation">(</span> <span class="token number">0</span> <span class="token punctuation">,</span> _ <span class="token punctuation">,</span> _ <span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token string">"On the X-axis"</span> <span class="token punctuation">(</span> _ <span class="token punctuation">,</span> <span class="token number">0</span> <span class="token punctuation">,</span> _ <span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token string">"On the Y-axis"</span> <span class="token punctuation">(</span> _ <span class="token punctuation">,</span> _ <span class="token punctuation">,</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token string">"On the Z-axis"</span> _ <span class="token operator">-></span> <span class="token string">"Roaming the Universe"</span> <span class="token comment">-- list : ...</span> <span class="token comment">-- any : ...</span> <span class="token comment">-- day : ...</span> |
1 2 3 | <span class="token comment">-- ...</span> <span class="token hvariable">main</span> <span class="token operator">=</span> <span class="token hvariable">Html.text</span> <span class="token punctuation">(</span> <span class="token hvariable">Tell.position</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">,</span> <span class="token number">3</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> |
http://localhost:8000/src/Main.elm
Recursion
After knowing how to create dynamic logic for the code based on the type and format of the data, we need another tool to support iterative operations on the List
dataset. We already know how to use this tool before. The definition of recursion
was mentioned in the Imperative & Declarative article of the Self-Taught Web Programming Series.
1 2 3 4 5 6 7 | <span class="token keyword">module</span> <span class="token constant">Recursion</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span> <span class="token hvariable">sumIntList</span> <span class="token punctuation">)</span> <span class="token hvariable">sumIntList</span> <span class="token operator">:</span> <span class="token constant">List</span> <span class="token constant">Int</span> <span class="token operator">-></span> <span class="token constant">Int</span> <span class="token hvariable">sumIntList</span> <span class="token hvariable">range</span> <span class="token operator">=</span> <span class="token keyword">case</span> <span class="token hvariable">range</span> <span class="token keyword">of</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token operator">-></span> <span class="token number">0</span> <span class="token hvariable">first</span> <span class="token operator">::</span> <span class="token hvariable">rest</span> <span class="token operator">-></span> <span class="token hvariable">first</span> <span class="token operator">+</span> <span class="token punctuation">(</span> <span class="token hvariable">sumIntList</span> <span class="token hvariable">rest</span> <span class="token punctuation">)</span> |
1 2 3 4 5 6 7 | <span class="token keyword">module</span> <span class="token constant">Main</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span> <span class="token hvariable">main</span> <span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Html <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span> <span class="token operator">..</span> <span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Recursion <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span> <span class="token operator">..</span> <span class="token punctuation">)</span> <span class="token hvariable">main</span> <span class="token operator">:</span> <span class="token constant">Html</span> <span class="token hvariable">message</span> <span class="token hvariable">main</span> <span class="token operator">=</span> <span class="token hvariable">Html.text</span> <span class="token punctuation">(</span> <span class="token hvariable">String.fromInt</span> <span class="token punctuation">(</span> <span class="token hvariable">Recursion.sumIntList</span> <span class="token punctuation">(</span> <span class="token hvariable">List.range</span> <span class="token number">0</span> <span class="token number">9</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> |
http://localhost:8000/src/Main.elm
Uh… now that I’m writing this, I’ve noticed that we need a solution to shorten the sub-program
calls that stack multiple layers like that. The parentheses placed on the same line of text will be quite difficult to recognize quickly when we skim the code.
1 2 3 | <span class="token comment">-- ...</span> <span class="token hvariable">main</span> <span class="token operator">=</span> <span class="token hvariable">Html.text</span> <span class="token operator"><|</span> <span class="token hvariable">String.fromInt</span> <span class="token operator"><|</span> <span class="token hvariable">Recursion.sumIntList</span> <span class="token operator"><|</span> <span class="token hvariable">List.range</span> <span class="token number">0</span> <span class="token number">9</span> |
Simply, for every pair of parentheses, we will replace it with a <|
. symbol to pass the result of the inner sub-program
to the outside on the left side. You can also use the |>
symbols to arrange the order of the sub-program
in reverse or the vertical list is also very easy to follow. However, such a sequence of writing will make our logical reasoning pattern
inclined towards Imperative
and will definitely affect the familiarity of thinking about solving problems in a recursion
way, which is especially important in this environment. Declarative
field.
Everyone’s choice will probably be different. I choose to keep the order of writing the names of the sub-program
recursively. And when writing a vertical list, each symbol <|
will be able to understand that the result of code execution will be returned to the above line.
1 2 3 4 5 6 | <span class="token comment">-- ...</span> <span class="token hvariable">main</span> <span class="token operator">=</span> <span class="token hvariable">Html.text</span> <span class="token operator"><|</span> <span class="token hvariable">String.fromInt</span> <span class="token operator"><|</span> <span class="token hvariable">Recursion.sumIntList</span> <span class="token operator"><|</span> <span class="token hvariable">List.range</span> <span class="token number">0</span> <span class="token number">9</span> |
Recursion in JS
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token comment">// -- main : any => null</span> <span class="token keyword">const</span> <span class="token function-variable function">main</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token parameter">_</span> <span class="token punctuation">)</span> <span class="token operator">=></span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token function">sumNumberArray</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">,</span> <span class="token number">3</span> <span class="token punctuation">,</span> <span class="token number">4</span> <span class="token punctuation">,</span> <span class="token number">5</span> <span class="token punctuation">,</span> <span class="token number">6</span> <span class="token punctuation">,</span> <span class="token number">7</span> <span class="token punctuation">,</span> <span class="token number">8</span> <span class="token punctuation">,</span> <span class="token number">9</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token comment">// -- sumNumberArray : [number] -> number</span> <span class="token keyword">const</span> <span class="token function-variable function">sumNumberArray</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token parameter">numberArray</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">var</span> <span class="token punctuation">[</span> first <span class="token punctuation">,</span> <span class="token operator">...</span> rest <span class="token punctuation">]</span> <span class="token operator">=</span> numberArray <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> numberArray <span class="token punctuation">.</span> length <span class="token operator">==</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token number">0</span> <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token string">"any-other-case"</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> first <span class="token operator">+</span> <span class="token function">sumNumberArray</span> <span class="token punctuation">(</span> rest <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// -- start program</span> <span class="token function">main</span> <span class="token punctuation">(</span> <span class="token number">Infinity</span> <span class="token punctuation">)</span> |
[Declarative Programming + Elm] Lesson 8 – Conditional Expression