<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: CloudHolic</title>
    <description>The latest articles on Forem by CloudHolic (@cloudholic).</description>
    <link>https://forem.com/cloudholic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1000698%2F5df9c8cd-121d-4d9e-bedd-a0d5671b5024.jpeg</url>
      <title>Forem: CloudHolic</title>
      <link>https://forem.com/cloudholic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/cloudholic"/>
    <language>en</language>
    <item>
      <title>F# Tutorial (6) - Pipeline</title>
      <dc:creator>CloudHolic</dc:creator>
      <pubDate>Tue, 03 Jan 2023 02:49:36 +0000</pubDate>
      <link>https://forem.com/cloudholic/f-tutorial-6-pipeline-2phd</link>
      <guid>https://forem.com/cloudholic/f-tutorial-6-pipeline-2phd</guid>
      <description>&lt;p&gt;이번 글에선 F#만의 독특한 문법인 pipeline에 대해 알아보겠습니다.&lt;/p&gt;

&lt;h4&gt;
  
  
  Composition
&lt;/h4&gt;

&lt;p&gt;다음의 두 함수를 생각해봅시다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;negate&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;square&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;그리고 이 두 함수를 순차적으로 적용해야 한다고 가정해봅시다. 그러면 다음과 같이 작성할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;square&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;     &lt;span class="c1"&gt;// 25&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;negate&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;    &lt;span class="c1"&gt;// -25&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이걸 한 문장으로 줄이면 다음과 같겠죠.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;negate&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;square&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// -25&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;F#에서는 이걸 함수의 composition이라 부르고, 다음과 같이 정의합니다.&lt;br&gt;
(함수의 이름이 연산자로만 구성되어 있을 경우, &lt;code&gt;let&lt;/code&gt;으로 선언할 때 함수명 앞뒤로 괄호를 붙여 함수임을 명확히 합니다.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="o"&gt;(&amp;gt;&amp;gt;)&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="o"&gt;(&amp;lt;&amp;lt;)&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; 연산자를 사용하며, 각각 정방향, 역방향 composition이라고 합니다.&lt;br&gt;
&lt;code&gt;f&lt;/code&gt;의 type이 &lt;code&gt;'T1 -&amp;gt; 'T2&lt;/code&gt;, &lt;code&gt;g&lt;/code&gt;의 type이 &lt;code&gt;'T2 -&amp;gt; 'T3&lt;/code&gt;이면, &lt;code&gt;f &amp;gt;&amp;gt; g&lt;/code&gt;의 type은 &lt;code&gt;'T1 -&amp;gt; 'T3&lt;/code&gt;가 되겠죠?&lt;br&gt;
&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; 연산자 자체만 놓고 보자면 &lt;code&gt;('T1 -&amp;gt; 'T2) -&amp;gt; ('T2 -&amp;gt; 'T3) -&amp;gt; 'T1 -&amp;gt; 'T3&lt;/code&gt;가 될 겁니다.&lt;br&gt;
물론 역방향 composition에 대해서도 같은 논리로 type을 구할 수 있겠고요.&lt;/p&gt;

&lt;p&gt;Composition을 사용해서 위에서 정의한 &lt;code&gt;negate&lt;/code&gt;와 &lt;code&gt;square&lt;/code&gt; 함수를 합쳐보면 다음과 같이 쓸 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;negateSquare&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;square&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;negate&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;negateSquare&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;     &lt;span class="c1"&gt;// -25&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; 연산자는 함수 2개를 받아서 함수를 리턴한다는 점을 기억하시면 되겠습니다.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pipeline
&lt;/h4&gt;

&lt;p&gt;Pipeline은 composition과 비슷하면서도 다릅니다. 다음의 두 함수를 생각해봅시다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;oddNums&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;squareNums&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;두 함수 다 list를 인자로 받으며, &lt;code&gt;oddNums&lt;/code&gt; 함수는 그 중 홀수인 원소만을 리턴하고, &lt;code&gt;squareNums&lt;/code&gt; 함수는 각 원소를 제곱해서 리턴합니다. 이 두 함수를 합친 함수, 즉 주어진 list에서 홀수인 원소만을 찾아 그것을 제곱한 결과를 모은 list를 리턴하는 함수는 다음과 같이 쓸 수 있을 겁니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;combine1&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;odds&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;squares&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;odds&lt;/span&gt;
    &lt;span class="n"&gt;squares&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;보시면 이 둘을 합친 함수 &lt;code&gt;combine1&lt;/code&gt;에서는 인자로 &lt;code&gt;values&lt;/code&gt;라는 list를 전달받고, 이 list는 &lt;code&gt;odds&lt;/code&gt;로, 또 &lt;code&gt;squares&lt;/code&gt;로 흘러갑니다. 그런데 사실 이전 결과값을 그대로 쓰는 것이 명확하다면, 이런 식으로 값의 이름을 계속 전달해주는 것은 불필요한 syntax가 되겠죠.&lt;br&gt;
그래서 F#에서는 데이터를 자연스럽게 넘기기 위해 pipeline이라는 개념을 도입했습니다. 다음과 같이 말이죠.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="o"&gt;(|&amp;gt;)&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="o"&gt;(&amp;lt;|)&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;|&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;|&lt;/code&gt; 연산자를 사용하며, 각각 정방향, 역방향 pipeline이라고 부릅니다. &lt;code&gt;f&lt;/code&gt;의 type을 &lt;code&gt;'T&lt;/code&gt;, &lt;code&gt;x&lt;/code&gt;의 type을 &lt;code&gt;'T -&amp;gt; 'U&lt;/code&gt;라고 하면 &lt;code&gt;|&amp;gt;&lt;/code&gt;의 type은 &lt;code&gt;'T -&amp;gt; ('T -&amp;gt; 'U) -&amp;gt; 'U&lt;/code&gt;가 될 겁니다. 역방향도 같은 논리로 type을 구할 수 있겠죠.&lt;/p&gt;

&lt;p&gt;역방향 pipeline의 경우 얼핏 보기엔 아무런 의미가 없어 보이지만 괄호 없이 연산의 우선순위를 바꿔 가독성을 높이는 데에 사용할 수 있습니다. 아주 간단한 예시를 보죠.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Will be [2; 4; 6; 8; 10]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Will be [4; 16; 36; 64; 100]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;result2&lt;/code&gt;를 역방향 pipeline 없이 사용하려면 &lt;code&gt;List.filter (fun x -&amp;gt; x % 2 = 0) (List.map (fun x -&amp;gt; x * x) [1..10])&lt;/code&gt;과 같이 써야 합니다. 이는 너무 길고 괄호가 중첩되어서 들어가 복잡하기까지 하죠.&lt;/p&gt;

&lt;p&gt;이제 위의 예시에서 사용했던 &lt;code&gt;odds&lt;/code&gt;와 &lt;code&gt;squares&lt;/code&gt;를 합쳐볼까요? 다음과 같이 작성하면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;combine2&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;values&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;처음에 인자로 받은 &lt;code&gt;values&lt;/code&gt;에서 시작하여 그 값을 그대로 &lt;code&gt;List.filter&lt;/code&gt; 함수의 마지막 인자로 넘깁니다. 함수의 리턴값은 그 함수가 마지막에 계산한 식의 리턴값이 되기 때문에 별도로 리턴할 필요는 없습니다.&lt;/p&gt;

&lt;p&gt;만일 pipeline으로 데이터를 2개 전달하고 싶다면 어떻게 해야 할까요? F#에서는 이를 위해 &lt;code&gt;||&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;||&lt;/code&gt; 연산을 제공합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="o"&gt;(||&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="o"&gt;(&amp;lt;||)&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;위와 같이 tuple의 형태로 데이터를 넘기고, 이를 받는 함수에서는 튜플을 자동적으로 풀어서 계산을 수행합니다.&lt;/p&gt;

&lt;p&gt;3개의 데이터를 전달하고 싶다면 같은 형태로 &lt;code&gt;|||&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;|||&lt;/code&gt; 연산을 사용하면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="o"&gt;(|||&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="o"&gt;(&amp;lt;|||)&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;삼중 pipeline 연산자도 크게 다르지 않습니다. 인자가 1개 더 늘어났다는 점만 빼고 말이죠.&lt;/p&gt;

&lt;p&gt;F#에서 제공하는 pipeline 연산자는 여기까지입니다. 만일 4개 이상의 데이터를 pipeline으로 전달해야 한다면 직접 구현하셔야 합니다.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;다음 글에서는 pattern matching에 대해 다루겠습니다.&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>F# Tutorial (5) - Function</title>
      <dc:creator>CloudHolic</dc:creator>
      <pubDate>Tue, 03 Jan 2023 02:46:59 +0000</pubDate>
      <link>https://forem.com/cloudholic/f-tutorial-5-function-424h</link>
      <guid>https://forem.com/cloudholic/f-tutorial-5-function-424h</guid>
      <description>&lt;p&gt;이번 글에선 F#의 함수에 대해 알아보겠습니다.&lt;/p&gt;

&lt;h4&gt;
  
  
  함수의 type
&lt;/h4&gt;

&lt;p&gt;다음의 간단한 함수를 봅시다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 함수의 이름은 &lt;code&gt;f&lt;/code&gt;이고, 인자를 &lt;code&gt;x&lt;/code&gt;란 이름으로 1개 받아 거기에 +1한 값을 리턴합니다. &lt;code&gt;x&lt;/code&gt;의 type은 명시되지 않았지만 &lt;code&gt;+ 1&lt;/code&gt;을 통해 &lt;code&gt;x&lt;/code&gt;는 &lt;code&gt;int&lt;/code&gt;임을 알 수 있습니다. 따라서 이 함수는 &lt;code&gt;int&lt;/code&gt;를 1개 받아 &lt;code&gt;int&lt;/code&gt;를 리턴하는 함수이며 &lt;code&gt;f&lt;/code&gt;의 type은 &lt;code&gt;int -&amp;gt; int&lt;/code&gt;로 정의할 수 있습니다. 즉, F#에서는 &lt;code&gt;(인자의 type) -&amp;gt; (리턴 type)&lt;/code&gt;의 형태로 함수의 type을 결정하게 됩니다.&lt;/p&gt;

&lt;h4&gt;
  
  
  함수 값
&lt;/h4&gt;

&lt;p&gt;F#에서는 함수를 정의할 때 값을 정의할 때와 마찬가지로 &lt;code&gt;let&lt;/code&gt;을 사용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;저번에 이에 대해서 언급했을 때는 &lt;code&gt;a&lt;/code&gt; 역시 인자가 0개고 &lt;code&gt;1&lt;/code&gt;을 리턴하는 함수로 생각하는게 이해하기 편할 것이라고 했습니다. 하지만 이는 이해를 돕기 위한 서술일 뿐 엄밀히 말해서 틀린 표현입니다. F#에서는 모든 함수를 값으로 취급합니다. 즉, &lt;code&gt;a&lt;/code&gt;는 &lt;code&gt;1&lt;/code&gt;로 정의된 값이고, &lt;code&gt;f&lt;/code&gt;는 &lt;code&gt;x -&amp;gt; x + 1&lt;/code&gt;로 정의된 값입니다.&lt;br&gt;
이 말은 곧 타 언어에서의 변수와 함수의 구분이 없다는 의미입니다. 타 언어에서 함수 내에 변수를 선언하거나 함수의 인자로 변수를 받듯이 F#에서는 함수 내에 함수를 선언하거나 함수를 인자로 받는 것이 자연스럽다는 의미입니다. 애초에 둘은 동일한 것이니까요.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
    &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;circleArea&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1415&lt;/span&gt;
    &lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;apply1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;increment&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apply1&lt;/span&gt; &lt;span class="n"&gt;increment&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;           &lt;span class="c1"&gt;// 11&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;함수의 리턴값은 가장 마지막에 실행된 식의 값으로 결정됩니다. 물론 &lt;code&gt;return&lt;/code&gt; 키워드를 사용해 명시적으로 지정해도 상관없습니다.&lt;br&gt;
저번에도 언급했듯, 둘 이상의 인자가 있으면 괄호 없이 순서대로 나열합니다.&lt;br&gt;
여담으로 위의 코드에서 &lt;code&gt;circleArea&lt;/code&gt; 함수의 경우 3.1415를 곱하는 연산이 포함되었기 때문에 컴파일러는 이 함수의 리턴값을 &lt;code&gt;float&lt;/code&gt;으로 판단합니다. 물론 인자에는 여전히 정수가 들어갈 수 있죠.&lt;/p&gt;
&lt;h4&gt;
  
  
  Lambda 함수
&lt;/h4&gt;

&lt;p&gt;이제는 굉장히 흔한 개념이 되어버린 익명 함수입니다. 말 그대로 이름이 정해지지 않은 함수로 F#에서는 &lt;code&gt;fun&lt;/code&gt; 키워드를 사용하여 나타냅니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;swap&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;swap&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;물론 익명 함수라고 해서 다른 함수를 정의하지 말라는 법은 없죠. 위의 코드에서처럼 얼마든지 다른 함수를 정의해서 사용해도 됩니다.&lt;br&gt;
마지막 익명 함수의 &lt;code&gt;in&lt;/code&gt; 키워드는 &lt;code&gt;let&lt;/code&gt; 바인딩이 유효한 구간을 명시적으로 지정할 때 쓰입니다.&lt;/p&gt;

&lt;p&gt;이러한 익명 함수는 물론 다른 함수의 인자 혹은 리턴값으로 사용될 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;// [2; 3; 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;map&lt;/code&gt;에 대한 건 이 글의 뒷부분에 나옵니다. 이런 방식으로 익명 함수를 사용할 수 있다는 것을 알아두시면 되겠습니다.&lt;/p&gt;

&lt;h4&gt;
  
  
  재귀 함수
&lt;/h4&gt;

&lt;p&gt;재귀 함수라는 개념 자체는 딱히 F#을 비롯한 FP언어만의 전유물은 아닙니다. F#이라고 해서 그 의미가 달라지지도 않고요. 하지만 F#에는 재귀 함수에 대한 특별한 룰이 한 가지 존재합니다. 함수를 정의할 때 &lt;code&gt;let&lt;/code&gt;을 썼었는데, 재귀 함수의 경우 &lt;code&gt;rec&lt;/code&gt; 키워드를 &lt;code&gt;let&lt;/code&gt; 다음에 이어서 써야 합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;rec&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(&lt;code&gt;match&lt;/code&gt; 및 &lt;code&gt;|&lt;/code&gt;에 대해서는 나중에 다룹니다.)&lt;br&gt;
매우 간단하게 구현한 피보나치 수열을 계산하는 함수입니다.&lt;/p&gt;

&lt;p&gt;Haskell의 경우 재귀 함수라고 해서 특별한 키워드를 붙이진 않습니다. 하지만 F#에서는 반드시 &lt;code&gt;rec&lt;/code&gt; 키워드가 필요한데요, 이는 내부적인 구현의 차이 때문입니다.&lt;br&gt;
Haskell에서는 함수를 메모리에 저장할 때 실질적인 계산은 전혀 수행하지 않습니다. 그냥 하나의 'thunk'를 메모리에 할당하며 이 thunk의 계산이 실제로 필요할 때 그제서야 수행하게 돼죠. 이러한 구현 방식에선 이 thunk가 다른 thunk를 가리키든, 자기 자신을 가리키든 아무런 문제가 되지 않습니다.&lt;br&gt;
하지만 F#에서는 다릅니다. F#에서는 함수를 메모리에 저장할 때 이미 계산을 수행하며, 따라서 그 함수는 내부적인 로직이 전부 정해져 있어야 합니다. 만일 함수 내에서 자기 자신을 다시 호출한다면 이는 미완성된 로직이며 무한루프가 발생할 수 있습니다. 그 때문에 일반 함수와 재귀 함수를 반드시 구분해야 하고, 이를 위해 &lt;code&gt;rec&lt;/code&gt;이라는 키워드가 필요합니다.&lt;br&gt;
어떻게 보면 Haskell과 F#의 철학의 차이를 엿볼 수 있는 부분이 되겠습니다.&lt;/p&gt;
&lt;h4&gt;
  
  
  Currying
&lt;/h4&gt;

&lt;p&gt;위에서 함수의 type을 얘기할 때 인자가 1개인 함수에 대해서만 다뤘습니다. 인자가 2개 이상인 함수에 대해서 다루기 위해서는 currying 이라는 개념을 알아야 합니다.&lt;br&gt;
다음의 함수를 생각해 봅시다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;위에서 정의한 &lt;code&gt;add&lt;/code&gt; 함수는 &lt;code&gt;int&lt;/code&gt; 2개를 받아서 그걸 더한 결과를 리턴합니다.&lt;br&gt;
그러면 &lt;code&gt;add 5&lt;/code&gt;와 같이 인자를 불완전하게 제공하면 이건 뭐가 될까요?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;add 5&lt;/code&gt;는 &lt;code&gt;add&lt;/code&gt;에서 첫 번째 인자만 제공한 형태이므로 제대로 계산하기 위해서는 인자가 1개 더 필요하고, 이 두 번째 인자에 5를 더한 값을 리턴할 것입니다. 바꿔 말해 &lt;code&gt;add 5&lt;/code&gt;는 &lt;code&gt;int&lt;/code&gt;형 인자를 1개 받아 거기에 5를 더한 값을 리턴하는 함수라는 이야기고, 따라서 다음과 같은 코드가 성립할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;add5&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add5&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;     &lt;span class="c1"&gt;// 6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;아예 &lt;code&gt;add 5&lt;/code&gt;를 별도의 함수로 지정해도 아무 문제가 없습니다. 이처럼 F#에서는 어떤 함수가 받은 인자가 필요한 인자보다 부족하다면, 이것을 나머지 인자를 요구하는 새 함수로 취급합니다. 이러한 개념을 currying이라고 부르며, F#은 Haskell과 함께 FP 언어 중에서도 currying 개념을 잘 지원하는 언어 중 하나입니다.&lt;/p&gt;

&lt;p&gt;그럼 currying을 염두에 두고 &lt;code&gt;add&lt;/code&gt; 함수를 다시 살펴봅시다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;add&lt;/code&gt; 함수에 대해 이번엔 다르게 해석해 보죠. 먼저 &lt;code&gt;add a&lt;/code&gt; 함수는 &lt;code&gt;int&lt;/code&gt;를 1개 받아서 그 값과 &lt;code&gt;a&lt;/code&gt;를 더한 값을 리턴합니다.&lt;br&gt;
그러면 &lt;code&gt;add&lt;/code&gt; 함수는 &lt;code&gt;int&lt;/code&gt;를 1개 받아서 &lt;code&gt;add a&lt;/code&gt; 함수를 리턴한다고 볼 수 있습니다.&lt;br&gt;
즉 &lt;code&gt;add&lt;/code&gt;함수는 &lt;code&gt;int&lt;/code&gt;를 1개 받아서 &lt;code&gt;int -&amp;gt; int&lt;/code&gt; 함수를 리턴하는 함수이므로 &lt;code&gt;add&lt;/code&gt;의 type은 &lt;code&gt;int -&amp;gt; (int -&amp;gt; int)&lt;/code&gt;라고 볼 수 있습니다.&lt;br&gt;
F#은 currying 지원이 잘 되어있기 때문에 결국 괄호를 생략해도 무방하며 &lt;code&gt;int -&amp;gt; int -&amp;gt; int&lt;/code&gt;로 표기할 수 있습니다.&lt;/p&gt;

&lt;p&gt;즉, F#에서는 인자가 여러 개 있는 함수라면 자동적으로 currying이 된 것으로 취급하며 따라서 중간에서 얼마든지 끊어서 쓸 수 있다는 이야기입니다. 그리고 그러한 함수의 type은 &lt;code&gt;(인자1의 type) -&amp;gt; (인자2의 type) -&amp;gt; ... -&amp;gt; (리턴 type)&lt;/code&gt;의 형태가 되겠죠.&lt;/p&gt;

&lt;p&gt;만일 특별한 이유가 있어 currying을 막고 싶다면 어떻게 해야 할까요? F#에서는 그럴 경우 tuple을 사용하라고 합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;add1&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;add2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 두 함수는 결과적으로는 같은 일을 하지만 세부적으론 좀 다릅니다. &lt;code&gt;add1&lt;/code&gt;의 type은 &lt;code&gt;int -&amp;gt; int -&amp;gt; int&lt;/code&gt;이고, &lt;code&gt;add2&lt;/code&gt;의 type은 &lt;code&gt;int * int -&amp;gt; int&lt;/code&gt;입니다. 또한 &lt;code&gt;add1&lt;/code&gt;은 currying이 가능하여 &lt;code&gt;add1 1&lt;/code&gt;과 같은 식으로 쓸 수 있지만, &lt;code&gt;add2&lt;/code&gt;는 currying이 불가능하여 이런 식으로 나눌 수 없습니다.&lt;/p&gt;

&lt;h4&gt;
  
  
  inline 함수
&lt;/h4&gt;

&lt;p&gt;F#에도 inline 함수가 있으며 함수 선언에 &lt;code&gt;inline&lt;/code&gt; 키워드를 붙여서 만듭니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="n"&gt;increment&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;여기까지만 보면 타 언어에서도 흔히 볼 수 있는 inline 함수지만, FP 언어로써의 특성과 F#의 type inference로 인해 다소 특이한 사용법이 존재합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;add1&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="n"&gt;add2&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;다시 한번 &lt;code&gt;add&lt;/code&gt; 함수를 가져오겠습니다. &lt;code&gt;add1&lt;/code&gt; 함수의 경우 두 인자 &lt;code&gt;a&lt;/code&gt;와 &lt;code&gt;b&lt;/code&gt;의 type이 정해져있지 않지만 F#의 type inference로 인해 적절한 type으로 고정되게 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add1&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;          &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add1&lt;/span&gt; &lt;span class="s2"&gt;"dog"&lt;/span&gt; &lt;span class="s2"&gt;"cat"&lt;/span&gt;      &lt;span class="c1"&gt;// error!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;즉, &lt;code&gt;result1&lt;/code&gt;을 실행하면서 F# compiler는 &lt;code&gt;add1&lt;/code&gt;이 &lt;code&gt;int -&amp;gt; int -&amp;gt; int&lt;/code&gt; 함수라는 것을 알게 되고, 따라서 &lt;code&gt;result2&lt;/code&gt;를 실행할 땐 주어진 인자가 &lt;code&gt;int&lt;/code&gt;가 아니므로 에러가 발생하게 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add2&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;          &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result4&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add2&lt;/span&gt; &lt;span class="s2"&gt;"dog"&lt;/span&gt; &lt;span class="s2"&gt;"cat"&lt;/span&gt;      &lt;span class="c1"&gt;// "dogcat"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;inline 함수는 좀 달라집니다. &lt;code&gt;result3&lt;/code&gt;을 실행하면서 F# compiler는 &lt;code&gt;add2&lt;/code&gt;의 type을 고려하지 않고 본문을 그대로 옮겨놓으며, 따라서 여기서의 &lt;code&gt;add2&lt;/code&gt;는 &lt;code&gt;int -&amp;gt; int -&amp;gt; int&lt;/code&gt;가 됩니다. &lt;code&gt;result 4&lt;/code&gt;를 실행할 때에도 역시 본문을 그대로 옮겨놓으며, 따라서 여기서의 &lt;code&gt;add2&lt;/code&gt;는 &lt;code&gt;string -&amp;gt; string -&amp;gt; string&lt;/code&gt;이 됩니다. 즉, 어떠한 type을 가져다놔도 &lt;code&gt;add2&lt;/code&gt; 함수 자체에서 에러가 나는 것이 아닌 이상 문제가 없습니다.&lt;/p&gt;

&lt;p&gt;이를 통해 동일한 표현식의, 서로 다른 type에서 적용되어야 할 함수를 &lt;code&gt;inline&lt;/code&gt; 키워드를 사용하여 마치 오버로딩과 유사하게 흉내낼 수 있습니다.&lt;/p&gt;

&lt;h4&gt;
  
  
  iter, map, filter, fold
&lt;/h4&gt;

&lt;p&gt;이번엔 저번에 미처 다루지 못한 나머지 collection 내장 함수들 중 일부를 다루겠습니다.&lt;br&gt;
여기 적힌 함수들은 foldBack을 제외하면 전부 list, 배열, sequence에서 사용할 수 있으며, 각각의 collection에서 특정 조건에 따라 함수를 사용할 수 있게 해주는 내장 함수입니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1) iter&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;iter&lt;/code&gt;는 collection의 각각의 원소들에 대해 주어진 함수를 실행할 수 있게 해줍니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"%d "&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt;
&lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iteri&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;printfn&lt;/span&gt; &lt;span class="s2"&gt;"Index %d: %d "&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;위의 코드에서도 알 수 있듯이 collection의 각각의 원소에 대해 같이 인자로 넘겨주는 함수를 실행시킬 뿐 그 리턴값은 전혀 신경쓰지 않습니다. &lt;code&gt;iter&lt;/code&gt;는 각 원소를 넘겨주며, 만일 index도 같이 필요하다면 &lt;code&gt;iteri&lt;/code&gt;를 사용하시면 됩니다. 이 경우 index, 원소 순서대로 인자를 넘겨주게 됩니다.&lt;/p&gt;

&lt;p&gt;만일 2개의 collection에 대해 사용하고자 한다면 &lt;code&gt;iter2&lt;/code&gt;, &lt;code&gt;iteri2&lt;/code&gt; 함수를 사용하면 됩니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) map&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;map&lt;/code&gt;은 collection의 각각의 원소들에 대해 주어진 함수를 실행하여, 그 결과를 모아 새 collection으로 리턴해줍니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt;       &lt;span class="c1"&gt;// [2; 3; 4]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mapi&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt;    &lt;span class="c1"&gt;// [1; 3; 5]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;iter&lt;/code&gt;와의 차이점을 눈치채셨나요? &lt;code&gt;iter&lt;/code&gt;는 리턴값 없이 실행만 할 뿐이지만, &lt;code&gt;map&lt;/code&gt;은 구체적인 리턴값이 존재해야 합니다. 그래야 그 결과를 모아 collection으로 만들어 줄 수 있거든요. &lt;code&gt;iter&lt;/code&gt;와 &lt;code&gt;iteri&lt;/code&gt;의 관계와 마찬가지로, index가 필요하다면 &lt;code&gt;mapi&lt;/code&gt;를 사용하면 됩니다.&lt;/p&gt;

&lt;p&gt;또한 &lt;code&gt;iter&lt;/code&gt;와 마찬가지로 &lt;code&gt;map2&lt;/code&gt;, &lt;code&gt;mapi2&lt;/code&gt;, &lt;code&gt;map3&lt;/code&gt;, &lt;code&gt;mapi3&lt;/code&gt; 등 여러 개의 collection에 대한 함수들도 존재합니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3) filter&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;filter&lt;/code&gt;는 collection의 각각의 원소들에 대해 주어진 함수를 실행하여, 그 중 &lt;code&gt;true&lt;/code&gt;가 나오는 것들만 모아 새 collection으로 리턴해줍니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;evenList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt;   &lt;span class="c1"&gt;// [2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;filter&lt;/code&gt;를 사용할 때 같이 제공되어야 할 함수는 반드시 &lt;code&gt;bool&lt;/code&gt;을 리턴해야 합니다.&lt;/p&gt;

&lt;p&gt;또한 &lt;code&gt;map&lt;/code&gt;과 &lt;code&gt;filter&lt;/code&gt;를 합친 느낌의 &lt;code&gt;choose&lt;/code&gt;라는 내장 함수도 존재합니다. &lt;code&gt;choose&lt;/code&gt;는 collection의 각각의 원소들에 대해 주어진 함수를 실행하여, 그 중 &lt;code&gt;Some(x)&lt;/code&gt;가 나오는 것들의 &lt;code&gt;x&lt;/code&gt;값만 모아 새 collection으로 리턴해줍니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4) fold&lt;/strong&gt;&lt;br&gt;
여태까지 살펴본 내장 함수들은 전부 각 원소들에 대해 독립적으로 수행했습니다. 하지만 때로는 이전 원소까지의 결과를 누적해서 적용해야 하는 경우도 있죠. 그럴 때 &lt;code&gt;fold&lt;/code&gt;를 사용합니다.&lt;br&gt;
&lt;code&gt;fold&lt;/code&gt;는 인자로 넘겨줄 함수가 원소값을 받을 인자 외에 'accumulator'라는 인자를 하나 더 가져야 합니다. 이 accumulator는 그 이전 원소까지의 실행 결과를 담게 되죠.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sumList&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sumList&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;       &lt;span class="c1"&gt;// 15&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reverseList&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="bp"&gt;[]&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reverseList&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="c1"&gt;// [5; 4; 3; 2; 1]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;위의 코드에서 보시다시피 accumulator에는 무엇이든 올 수 있으며, 그 type은 &lt;code&gt;fold&lt;/code&gt;의 두 번째 인자인 '초기 accumulator 값'으로 정해집니다.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fold&lt;/code&gt;에도 파생된 다른 함수들이 존재합니다. 먼저, collection을 역순으로 탐색하는 &lt;code&gt;foldBack&lt;/code&gt;이 있으며, 2개의 collection에 대해 동일한 작업을 수행하는 &lt;code&gt;fold2&lt;/code&gt;와 &lt;code&gt;foldBack2&lt;/code&gt; 함수가 존재합니다. 주의할 점은 &lt;code&gt;foldBack&lt;/code&gt;과 &lt;code&gt;foldBack2&lt;/code&gt; 함수의 경우 해당 collection의 마지막부터 역순으로 탐색하기 때문에, 무한대의 개념을 다루고 lazy evaluation을 수행하는 sequence에서는 지원되지 않는다는 것입니다.&lt;/p&gt;

&lt;p&gt;또한 &lt;code&gt;fold&lt;/code&gt;는 모든 중간 계산을 생략하고 제일 마지막에 계산된 값을 리턴하는데, 그 중간 과정을 모두 보고 싶다면 &lt;code&gt;scan&lt;/code&gt;을 사용하면 됩니다. &lt;code&gt;scan&lt;/code&gt;은 주어진 함수를 각 원소에 대해 순차적으로 실행하며 각각의 원소마다 나오는 중간 결과값(즉, accumulator 값)을 모은 collection을 리턴합니다.&lt;/p&gt;




&lt;p&gt;혹시 지금까지의 예시 코드 중에 조건문과 반복문이 전혀 없다는 것을 눈치채셨나요? FP에서는 조건문과 반복문에 직접적으로 대응되는 &lt;code&gt;if&lt;/code&gt; 및 &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt; 등을 사용하는 것을 지양합니다. 직접적인 control flow를 사용하게 되면 함수가 간단하지 못하거든요. 물론 F#은 C#과의 호환성을 위해 해당 statement가 존재하지만, 가급적 사용하지 않는 것이 좋습니다.&lt;/p&gt;

&lt;p&gt;그렇다고 해서 조건문과 반복문에 해당하는 기능이 아예 존재하지 않는다는 이야기는 아닙니다. 반복문의 경우 위에서 살펴본 재귀 함수, 혹은 방금 다뤘던 다양한 내장 함수를 사용하면 되며 이게 FP 스타일에 더 알맞습니다. &lt;/p&gt;

&lt;p&gt;조건문을 FP 스타일로 어떻게 쓰는지는 나중에 알아보겠습니다.&lt;/p&gt;

&lt;h4&gt;
  
  
  Etc.
&lt;/h4&gt;

&lt;p&gt;지금까지는 매우 단편적인 함수들만 살펴봤습니다. 하지만 F#도 엄연히 자체적으로 실행이 가능한 언어인 만큼, 진입점이 존재합니다.&lt;br&gt;
F#의 진입점은 다음과 같이 정의됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;EntryPoint&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="c1"&gt;// Do whatever wants.&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;main&lt;/code&gt; 함수의 위에 &lt;code&gt;[&amp;lt;EntryPoint&amp;gt;]&lt;/code&gt;라는 특성을 달아야 하며, &lt;code&gt;main&lt;/code&gt; 함수의 type은 &lt;code&gt;string array -&amp;gt; int&lt;/code&gt;로 고정됩니다.&lt;br&gt;
리턴값은 다른 C 계열 언어가 그렇듯 &lt;code&gt;0&lt;/code&gt;이면 정상 종료, 그 이외의 값이면 비정상 종료입니다.&lt;/p&gt;



&lt;p&gt;지금까지 함수를 선언할 때 항상 &lt;code&gt;let&lt;/code&gt;만을 사용했습니다. 물론 &lt;code&gt;let&lt;/code&gt;이 메모리에 값을 대입시키는 거의 유일한 방법인 것은 맞으나, 때로는 굳이 그 결과를 저장하지 않고 수행'만' 필요한 경우도 있습니다. 이럴 때 &lt;code&gt;do&lt;/code&gt;를 사용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="n"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Hello World"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;printf&lt;/code&gt; 함수를 실행하기만 하고 그 리턴값을 취하지 않는다는 의미이며, 많은 경우 &lt;code&gt;do&lt;/code&gt;를 생략할 수 있습니다.&lt;br&gt;
주의할 점은, &lt;code&gt;do&lt;/code&gt;를 사용할 경우 그 다음에 오는 함수의 리턴값은 반드시 &lt;code&gt;unit&lt;/code&gt;이어야 한다는 점입니다.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;br&gt;
다음 글에서는 F#만의 고유한 문법인 pipeline에 대해 다루겠습니다.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>F# Tutorial (4) - Collection</title>
      <dc:creator>CloudHolic</dc:creator>
      <pubDate>Tue, 03 Jan 2023 02:44:32 +0000</pubDate>
      <link>https://forem.com/cloudholic/f-tutorial-4-collection-777</link>
      <guid>https://forem.com/cloudholic/f-tutorial-4-collection-777</guid>
      <description>&lt;p&gt;이번 글에선 F#에서 제공하는 collection에 대해 알아보겠습니다.&lt;br&gt;
F#에서 지원하는 collection은 크게 List, Array, Sequence의 3종류가 있습니다.&lt;/p&gt;
&lt;h4&gt;
  
  
  List
&lt;/h4&gt;

&lt;p&gt;List는 순서가 있고 immutable한 같은 type의 원소에 대한 collection입니다. 내부적으로 Singly linked list로 구현되어 있으며, 따라서 iteration은 효율적이지만 random access에는 그리 적합하지 않습니다.&lt;/p&gt;

&lt;p&gt;F#에서 list는 &lt;code&gt;'T list&lt;/code&gt;라는 type을 가지며 &lt;code&gt;[]&lt;/code&gt;를 사용해서 정의합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;[]&lt;/span&gt;          &lt;span class="c1"&gt;// empty list&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;    &lt;span class="c1"&gt;// 1, 2, 3을 원소로 갖는 list&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;           &lt;span class="c1"&gt;// 여러 줄에 걸쳐 정의할 수도 있습니다.&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list4&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;       &lt;span class="c1"&gt;// 1~1000까지의 정수를 원소로 갖는 리스트&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List는 &lt;code&gt;::&lt;/code&gt;(cons) 연산자를 통해 원소를 list에 연결할 수 있습니다.&lt;br&gt;
List를 list에 연결하고 싶으면 &lt;code&gt;@&lt;/code&gt;연산자를 대신 사용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt;    &lt;span class="c1"&gt;// list2 = [ 100; 1; 2; 3; ]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;list2&lt;/span&gt;   &lt;span class="c1"&gt;// list3 = [ 1; 2; 3; 100; 1; 2; 3; ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;주의할 점은, list는 immutable한 collection이기 때문에 list에 대한 수정은 반드시 새 list를 만든다는 점입니다. 절대 기존 list를 수정해주지 않습니다.&lt;/p&gt;

&lt;p&gt;List는 Head와 Tail이라는 개념이 있습니다. Head는 list의 첫 번째 원소를 뜻하며, Tail은 그 나머지 전부를 모은 list를 뜻합니다. F#에서는 Head와 Tail이라는 property로 이를 지원합니다. 그 외에도 지원하는 property는 다음과 같습니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Head&lt;/td&gt;
&lt;td&gt;'T&lt;/td&gt;
&lt;td&gt;첫 번째 원소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tail&lt;/td&gt;
&lt;td&gt;'T list&lt;/td&gt;
&lt;td&gt;첫 번째 원소를 제외한 나머지 원소들의 list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Empty&lt;/td&gt;
&lt;td&gt;'T list&lt;/td&gt;
&lt;td&gt;동일한 type의 원소를 갖는 빈 list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IsEmpty&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;list가 비어있으면 true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Item&lt;/td&gt;
&lt;td&gt;'T&lt;/td&gt;
&lt;td&gt;특정 index의 원소 (zero-based)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Length&lt;/td&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;list의 원소의 개수&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;이미 한 번 언급했듯이, F#의 list에선 random access에 O(N)의 시간이 필요합니다. 따라서 List.Item(n)은 그다지 빠르지 않습니다.&lt;/p&gt;

&lt;h4&gt;
  
  
  배열(Array)
&lt;/h4&gt;

&lt;p&gt;배열은 고정된 크기의 mutable한 같은 type의 원소에 대한 collection입니다. 타 언어에서도 흔히 볼 수 있는 배열과 동일하며, 따라서 빠른 random access를 지원합니다.&lt;/p&gt;

&lt;p&gt;F#에서 배열은 &lt;code&gt;'T array&lt;/code&gt;라는 type을 가지며, &lt;code&gt;[| |]&lt;/code&gt;를 사용해서 정의합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;array1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;    &lt;span class="c1"&gt;// empty array&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;array2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;|]&lt;/span&gt; &lt;span class="c1"&gt;// 1, 2, 3을 원소로 갖는 배열&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;array3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[|&lt;/span&gt;         &lt;span class="c1"&gt;// 배열도 여러 줄에 걸쳐 정의할 수 있습니다.&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;|]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;array4&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeroCreate&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;    &lt;span class="c1"&gt;// 0을 10개 갖는 array&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;배열은 &lt;code&gt;[]&lt;/code&gt;를 통해 특정 원소에 접근할 수 있습니다. 늘 그렇듯 zero-base입니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;array1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;|]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;       &lt;span class="c1"&gt;// a = 2&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;array2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="c1"&gt;// array2 = [| 2; 3; 4; |]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;array3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array1&lt;/span&gt;&lt;span class="o"&gt;[..&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;    &lt;span class="c1"&gt;// array3 = [| 1; 2; 3; |]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;array4&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;..]&lt;/span&gt;    &lt;span class="c1"&gt;// array4 = [| 5; |]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;여기에서도 &lt;code&gt;..&lt;/code&gt;를 사용하여 범위를 지정할 수 있으며, 이를 slicing이라고 부릅니다. 주의할 점은 slicing을 사용할 경우, 실질적으로 해당되는 원소가 단 1개뿐이더라도 새 배열로 복사되어서 리턴한다는 점입니다. 이 경우에는 원본 배열을 변형시키지 않습니다.&lt;br&gt;
단일 index를 사용하여 배열에 접근한 경우, &lt;code&gt;&amp;lt;-&lt;/code&gt;로 해당 원소의 값을 수정할 수 있습니다.&lt;br&gt;
배열의 접근/수정의 경우 &lt;code&gt;Array.get&lt;/code&gt;, &lt;code&gt;Array.set&lt;/code&gt; 함수로도 동일한 작업을 수행 할 수 있으며, &lt;code&gt;Array.fill&lt;/code&gt; 함수를 사용해 여러 원소의 값을 일괄적으로 바꿀 수도 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;array1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="p"&gt;|]&lt;/span&gt;
&lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fill&lt;/span&gt; &lt;span class="n"&gt;array1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;    &lt;span class="c1"&gt;// array1의 2~20번째 원소의 값을 0으로 변경&lt;/span&gt;
&lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;array1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;      &lt;span class="c1"&gt;// array1의 2번째 원소의 값 = 0&lt;/span&gt;
&lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="n"&gt;array1&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;       &lt;span class="c1"&gt;// array1의 1번째 원소의 값을 10으로 변경&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;배열은 mutable하지만 fixed-size임에 주의해야 합니다. 이미 있는 원소의 값을 바꾸는건 자유롭지만 크기를 늘리는건 불가능합니다. &lt;code&gt;append&lt;/code&gt;를 수행할 경우 다른 collection과 마찬가지로 원본의 변경 없이 새 배열을 만들어 리턴합니다.&lt;/p&gt;

&lt;p&gt;다른 언어와 마찬가지로 F#에서는 다차원 배열을 지원합니다. 하지만 &lt;code&gt;[| |]&lt;/code&gt;를 사용하는 것이 아니라 &lt;code&gt;array2D&lt;/code&gt;, &lt;code&gt;array3D&lt;/code&gt;, &lt;code&gt;array4D&lt;/code&gt;를 사용해야만 합니다. 5차원 이상의 배열이 필요할 경우 직접 만들어야 합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;array2d1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array2D&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;];&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;물론 &lt;code&gt;[| |]&lt;/code&gt;를 사용하여 배열을 원소로 갖는 배열을 만들 수 있지만, index의 접근방법에서 다소 차이가 납니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;array1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[|&lt;/span&gt; &lt;span class="p"&gt;[|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;|];&lt;/span&gt; &lt;span class="p"&gt;[|&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;|];&lt;/span&gt; &lt;span class="p"&gt;|]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;array2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array2D&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;];&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;array1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;        &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="n"&gt;array2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;        &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2차원 배열의 type은 &lt;code&gt;'T[,]&lt;/code&gt;라고 정의되며, 3차원 배열은 &lt;code&gt;'T[,,]&lt;/code&gt;로 정의됩니다. 그 이상의 차원에 대해서도 동일한 규칙이 적용됩니다.&lt;br&gt;
각각의 차원에 대해 slicing을 적용할 수 있으며, 추가적으로 &lt;code&gt;*&lt;/code&gt;을 통해 해당 차원의 모든 index에 대응시킬 수 있습니다. 그 외에는 1차원 배열과 동일한 규칙으로 적용됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="n"&gt;matrix1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..,&lt;/span&gt; &lt;span class="o"&gt;*]&lt;/span&gt;
&lt;span class="n"&gt;matrix1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*]&lt;/span&gt;
&lt;span class="n"&gt;matrix1&lt;/span&gt;&lt;span class="o"&gt;[*,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;matrix1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Sequence
&lt;/h4&gt;

&lt;p&gt;Sequence는 동일한 type의 원소에 대한 논리적인 collection입니다. 다른 collection과는 다르게, sequence는 lazy evaluation을 지원합니다. 즉, 각각의 원소는 필요할 때 계산되며, 이 때문에 list나 array에 비해 요구하는 총 원소의 개수는 많지만 그들 전부가 필요하지는 않은 경우에 유용하게 사용할 수 있습니다.&lt;/p&gt;

&lt;p&gt;F#에서 sequence는 &lt;code&gt;seq&amp;lt;T'&amp;gt;&lt;/code&gt;라는 type을 가지며, &lt;code&gt;seq { }&lt;/code&gt;를 사용해서 정의합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;seq1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;                &lt;span class="c1"&gt;// empty sequence&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;seq2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;           &lt;span class="c1"&gt;// 1 ~ 5를 원소로 갖는 sequence&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;seq3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s2"&gt;"World"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}//&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"World"&lt;/span&gt;&lt;span class="err"&gt;를&lt;/span&gt; &lt;span class="err"&gt;원소로&lt;/span&gt; &lt;span class="err"&gt;갖는&lt;/span&gt; &lt;span class="n"&gt;sequence&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List나 배열과는 다르게 원소를 저장할 때 &lt;code&gt;yeild&lt;/code&gt;를 사용합니다. 이에 대한 내용은 나중에 다루겠습니다. 지금은 &lt;code&gt;yield&lt;/code&gt;를 사용해서 선언한다고만 알아두시면 됩니다.&lt;/p&gt;

&lt;p&gt;Sequence의 경우 lazy evaluation이 기본적으로 지원되는 collection이기 때문에 '무한'을 다루는 데 적합합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;seq1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;singleton&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;// 모든 원소가 10인 sequence&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;seq2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="n"&gt;seq1&lt;/span&gt;  &lt;span class="c1"&gt;// seq { 10; 10; 10; 10; 10; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;위 코드에서 &lt;code&gt;seq1&lt;/code&gt;은 길이가 딱히 정해져 있지 않습니다. 계산을 요청할 때마다 &lt;code&gt;10&lt;/code&gt;을 리턴할 뿐이죠. &lt;code&gt;Seq.take&lt;/code&gt; 혹은 &lt;code&gt;Seq.truncate&lt;/code&gt; 함수를 사용하여 원소 몇 개를 가져오거나 &lt;code&gt;Seq.skip&lt;/code&gt; 함수를 사용하여 몇 개를 건너뛸 수 있습니다.&lt;/p&gt;

&lt;h4&gt;
  
  
  내장 함수들
&lt;/h4&gt;

&lt;p&gt;각각의 collection에는 다양한 내장 함수들이 존재합니다. 각 collection에서 지원하는 모든 함수들의 목록은 &lt;a href="https://fsharp.github.io/fsharp-core-docs/reference/fsharp-collections-listmodule.html" rel="noopener noreferrer"&gt;List&lt;/a&gt;, &lt;a href="https://fsharp.github.io/fsharp-core-docs/reference/fsharp-collections-arraymodule.html" rel="noopener noreferrer"&gt;Array&lt;/a&gt;, &lt;a href="https://fsharp.github.io/fsharp-core-docs/reference/fsharp-collections-seqmodule.html" rel="noopener noreferrer"&gt;Sequence&lt;/a&gt;를 참고하시면 됩니다. 여기서는 그 중 간단하면서도 자주 쓰이는 일부만 다루며, 나머지 중 일부는 이후의 글에서 다루겠습니다. Collection의 종류에 따라 지원하는 함수의 종류가 조금씩 다르지만, 아래에서 다루는 함수들은 list, 배열, sequence에서 전부 지원하며, 함수의 형태는 각각 &lt;code&gt;List.func&lt;/code&gt;, &lt;code&gt;Array.func&lt;/code&gt;, &lt;code&gt;Seq.func&lt;/code&gt;의 형태입니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1) exists / forall&lt;/strong&gt;&lt;br&gt;
같이 제시된 함수의 조건을 만족하는 원소가 있는지를 체크하며 해당하는 원소가 하나라도 있다면 그 결과는 &lt;code&gt;true&lt;/code&gt;가 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;위의 예시에서는 &lt;code&gt;list1&lt;/code&gt;에서 4를 가진 원소가 있는지를 체크하며, 그러한 원소가 없으니 결과는 &lt;code&gt;false&lt;/code&gt;입니다.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;forall&lt;/code&gt;의 경우 &lt;code&gt;exists&lt;/code&gt;와는 다르게 모든 원소에 대해 주어진 조건을 통과하는지 체크합니다. 하나라도 실패한 원소가 있다면 그 결과는 &lt;code&gt;false&lt;/code&gt;가 됩니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) sort / sortBy&lt;/strong&gt;&lt;br&gt;
Collection의 원소를 정렬합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;              &lt;span class="c1"&gt;// [-4; 1; 2; 5; 8]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sortBy&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;abs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="c1"&gt;// [1; 2; -4; 5; 8]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;기본적인 &lt;code&gt;sort&lt;/code&gt; 함수는 오름차순으로 정렬합니다. 만일 크기 비교가 불가능한 type이거나 별도의 기준이 필요할 경우, &lt;code&gt;sortBy&lt;/code&gt; 함수를 통해 크기 비교의 기준이 될 함수를 같이 제공할 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3) find / tryFind&lt;/strong&gt;&lt;br&gt;
Collection에서 주어진 기준에 만족하는 첫 번째 원소를 찾습니다. 만일 해당하는 원소가 하나도 없다면 System.Collections.Generic.KeyNotFoundException 예외를 발생시킵니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;    &lt;span class="c1"&gt;// 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;위의 코드는 [1..100]에서 가장 먼저 등장하는 5의 배수를 찾으며, 그 결과는 5입니다.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tryFind&lt;/code&gt;함수를 사용하게 되면 예외를 발생시키지 않을 수 있으며, 검색에 실패할 경우 &lt;code&gt;None&lt;/code&gt;을, 성공할 경우 &lt;code&gt;Some(x)&lt;/code&gt;를 리턴하게 됩니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4) sum / sumBy / average / averageBy&lt;/strong&gt;&lt;br&gt;
Collection의 원소의 합(&lt;code&gt;sum&lt;/code&gt;), 평균(&lt;code&gt;average&lt;/code&gt;)를 계산합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sum1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// 55&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;avr1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;average&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;// 2.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sort&lt;/code&gt; 및 &lt;code&gt;sortBy&lt;/code&gt;의 관계와 같이, 만일 별도의 계산 함수가 필요하다면 &lt;code&gt;sumBy&lt;/code&gt;와 &lt;code&gt;averageBy&lt;/code&gt;를 사용하면 됩니다.&lt;/p&gt;

&lt;p&gt;Infinite sequence의 경우 에러가 나지는 않지만 의도하지 않은 결과가 나올 확률이 매우 높습니다. 무한으로 존재하는데 그걸 전부 더하라고 하면 무한루프가 일어나겠죠. 따라서 &lt;code&gt;take&lt;/code&gt; 등을 사용해 적절히 잘라준 후 사용해야 합니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5) zip / zip3 / unzip / unzip3&lt;/strong&gt;&lt;br&gt;
F#에서 &lt;code&gt;zip&lt;/code&gt;이란 2개의 collection을 각 원소가 기존 collection들을 묶은 tuple이 되는 하나의 collection으로 묶는 함수를, &lt;code&gt;unzip&lt;/code&gt;은 반대로 각 원소가 tuple인 collection을 tuple의 개수만큼 분리하는 함수를 뜻합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;zipList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt; &lt;span class="n"&gt;list2&lt;/span&gt;  &lt;span class="c1"&gt;// [(1, -1); (2, -2); (3, -3)]  &lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;listTuple&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unzip&lt;/span&gt; &lt;span class="n"&gt;zipList&lt;/span&gt;  &lt;span class="c1"&gt;// ([1; 2; 3], [-1; -2; -3])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;만일 3개의 collection에 대해 이 작업을 수행하고 싶다면 &lt;code&gt;zip3&lt;/code&gt;, &lt;code&gt;unzip3&lt;/code&gt; 함수를 사용하면 됩니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6) append / concat&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;append&lt;/code&gt; 함수는 list에서 다룬 &lt;code&gt;@&lt;/code&gt;과 동일한 역할을 합니다. 즉, 같은 type의 두 collection을 합쳐 새 collection으로 리턴합니다. 만일 세 개 이상의 collection에 대해 같은 일을 하고 싶다면, &lt;code&gt;concat&lt;/code&gt; 함수를 사용하면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// [1; 2; 3; 4; 5; 6]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;list2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;concat&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;  &lt;span class="c1"&gt;// [1; 2; 3; 4; 5; 6]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;concat&lt;/code&gt;함수는 인자의 개수가 정해지지 않았기 때문에 연결을 원하고자 하는 collection들의 list를 인자로 받습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7) 다른 collection으로의 변환&lt;/strong&gt;&lt;br&gt;
지금까지 알아본 collection들은 상호 변환이 가능합니다.&lt;br&gt;
&lt;code&gt;List.toSeq&lt;/code&gt;는 list를 sequence로 바꾸며, &lt;code&gt;List.ofSeq&lt;/code&gt;는 반대로 sequence를 list로 바꿔줍니다.&lt;br&gt;
배열에 대해서도 &lt;code&gt;List.toArray&lt;/code&gt;, &lt;code&gt;List.ofArray&lt;/code&gt; 함수가 존재하며, 다른 collection들도 이에 대응하는 함수들이 전부 존재합니다.&lt;br&gt;
&lt;code&gt;to*&lt;/code&gt;함수와 &lt;code&gt;of*&lt;/code&gt;함수는 성능상의 차이점은 전혀 없으니(즉, &lt;code&gt;List.ofSeq&lt;/code&gt;와 &lt;code&gt;Seq.toList&lt;/code&gt;는 내부적으로도 완벽하게 동일한 함수입니다.) 편하신 대로 사용하시면 됩니다.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;지금까지 기본적인 collection에 대해 간략하게 알아보았습니다. 다음 글에서는 F#을 비롯한 FP 언어의 근본이라고 할 수 있는 함수에 대해 더 자세히 알아보겠습니다.&lt;/p&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>F# Tutorial (3) - Tuple</title>
      <dc:creator>CloudHolic</dc:creator>
      <pubDate>Tue, 03 Jan 2023 02:40:54 +0000</pubDate>
      <link>https://forem.com/cloudholic/f-tutorial-3-tuple-2nl2</link>
      <guid>https://forem.com/cloudholic/f-tutorial-3-tuple-2nl2</guid>
      <description>&lt;p&gt;이번 글에선 F#에서의 Tuple에 대해 알아보겠습니다.&lt;/p&gt;

&lt;h4&gt;
  
  
  Definition
&lt;/h4&gt;

&lt;p&gt;Tuple은 1개 이상 type으로 이루어진 이름없는 값들의 그룹입니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"one"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"two"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"three"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"one"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;위의 예시들에서 볼 수 있듯이 각 원소들의 type이 달라도 상관없습니다.&lt;br&gt;
또한 FP에서 '값'이란 것은 결국 함수이기 때문에 안에 함수가 들어가도 상관없고요.&lt;/p&gt;

&lt;p&gt;또한 값을 여러 개 입력받을때도 유용하지만, 여러 개 출력할 때도 유용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;divRem&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;// x와 y를 동시에 리턴&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Type of tuple
&lt;/h4&gt;

&lt;p&gt;Tuple의 type은 &lt;code&gt;*&lt;/code&gt;를 사용해서 표기합니다.&lt;br&gt;
뒤에서 볼 struct tuple의 경우 기존 type을 &lt;code&gt;struct( )&lt;/code&gt;로 감싸주면 그게 곧 struct tuple의 type이 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"three"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;// int * float * string&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"three"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// struct (int * float * string)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  개별 원소에 접근하기
&lt;/h4&gt;

&lt;p&gt;이러한 tuple의 각 원소에 접근하는 방법엔 여러 가지가 있습니다.&lt;/p&gt;

&lt;p&gt;먼저 &lt;code&gt;let&lt;/code&gt; Binding을 사용할 수 있겠군요.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// a = 1, b = 2   &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;다음으론 내장 함수인 &lt;code&gt;fst&lt;/code&gt;, &lt;code&gt;snd&lt;/code&gt;를 사용하는 방법도 있습니다. &lt;code&gt;fst&lt;/code&gt;함수는 해당 tuple의 첫 번째 원소를, &lt;code&gt;snd&lt;/code&gt;함수는 두 번째 원소를 리턴해줍니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fst&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// c = 1&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;snd&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// d = 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;그런데 세번째 이후의 원소를 리턴하는 함수는 없습니다. 만일 필요하다면 아래와 같이 직접 만들 수는 있죠.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;third&lt;/span&gt; &lt;span class="o"&gt;(_,&lt;/span&gt; &lt;span class="o"&gt;_,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;나중에 알아볼 Pattern Matching을 이용해도 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;tuple1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;tuple1&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;printfn&lt;/span&gt; &lt;span class="s2"&gt;"Pair %A %A"&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;함수의 인자로 쓰는 거라면 아래처럼 명시적으로 각 원소로 분해해서 받아도 되고요.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y1&lt;/span&gt;&lt;span class="o"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y2&lt;/span&gt;&lt;span class="o"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x1&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y1&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tuple 내에서 관심이 없는 원소가 있다면, &lt;code&gt;_&lt;/code&gt;를 사용해 받으면 해당 원소에 대한 새 할당을 피할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;_)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 2는 버려집니다.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Struct tuple
&lt;/h4&gt;

&lt;p&gt;지금까지 사용한 tuple은 모두 reference tuple입니다. 이와는 반대로 struct tuple도 존재합니다. Struct tuple은 Reference tuple과 달리 value type이며, heap이 아닌 stack에 저장되어서 약간의 성능 향상을 꾀할 수 있습니다.&lt;/p&gt;

&lt;p&gt;Struct tuple은 다음과 같이 tuple 앞에 &lt;code&gt;struct&lt;/code&gt;가 붙는다는 것 외에 다른 모든 점이 동일합니다. 적어도 사용에 있어서는요.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;str_a&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// a = 1, b = 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;하지만 내부 구현은 전혀 다르기 때문에 reference tuple과 struct tuple 간의 암시적인 컨버팅은 불가능합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// Compile error!&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// Compile error!&lt;/span&gt;

&lt;span class="c1"&gt;// 이런 꼼수도 불가능합니다.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;convert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tpl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;)):&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tpl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reference tuple과 struct tuple 간에 컨버팅을 하고 싶다면, 다음과 같이 명시적으로 각각의 원소들을 새로 집어넣어서 새 tuple을 만들어야 합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;그러면 언제 struct tuple을 써야 할까요? 저는 크게 다음과 같은 케이스에서 사용을 고려할 수 있다고 생각합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;사용하고자 하는 tuple의 원소 개수가 많거나 개별 원소가 복잡한 type을 가지고 있을 때, 성능 향상을 위해 사용&lt;/li&gt;
&lt;li&gt;C#과의 interop가 필요한 경우&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 중 후자의 경우에 대해 더 알아보겠습니다. C# 7.0 이후 버전에서 tuple은 System.ValueTuple로 컴파일되며 이는 value type입니다. 그리고 F#에서의 struct tuple 역시 System.ValueTuple로 컴파일됩니다.&lt;br&gt;
즉, C#의 Tuple과 F#의 struct tuple은 완전히 동일한 타입이기 때문에 C#과의 interop를 고려하고 있다면 struct tuple을 사용해야만 합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Interop&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;AddOne&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;tpl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tpl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tpl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nc"&gt;Interop&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AddOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;    &lt;span class="c1"&gt;// x = 2, y = 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;위와 같이 C# Tuple과 F# struct tuple은 근본적으로 동일하기 때문에 별다른 과정 없이 자연스럽게 interop가 가능합니다.&lt;/p&gt;

&lt;p&gt;다음 글에선 Collection을 다루도록 하겠습니다.&lt;/p&gt;

</description>
      <category>fsharp</category>
    </item>
    <item>
      <title>F# Tutorial (2) - Basics</title>
      <dc:creator>CloudHolic</dc:creator>
      <pubDate>Tue, 03 Jan 2023 02:38:55 +0000</pubDate>
      <link>https://forem.com/cloudholic/f-tutorial-2-basics-86p</link>
      <guid>https://forem.com/cloudholic/f-tutorial-2-basics-86p</guid>
      <description>&lt;p&gt;본격적으로 F#을 시작해봅시다.&lt;/p&gt;

&lt;p&gt;먼저 F#은 닷넷 위에서 돌아가는 언어이기 때문에 닷넷 개발환경을 갖추시면 그게 곧 F#의 개발환경이 됩니다. 보통은 Visual Studio겠지만 Rider 혹은 VSCode 등의 텍스트 에디터를 사용하셔도 됩니다. 이도저도 다 귀찮다면 &lt;a href="https://try.fsharp.org/" rel="noopener noreferrer"&gt;Try F#&lt;/a&gt;에서 온라인으로 실행시켜 볼 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;let&lt;/code&gt; Binding
&lt;/h3&gt;

&lt;p&gt;F#은 함수형 언어입니다. 이 말은 모든 것을 함수로 취급하고 관리한다는 의미입니다. 따라서 엄밀히 말해서 함수형 언어에서는 변수라는 개념이 존재하지 않습니다.&lt;/p&gt;

&lt;p&gt;F#에서 함수를 선언할 때는 &lt;code&gt;let&lt;/code&gt;을 사용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;square&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;    &lt;span class="c1"&gt;// square(x) = x * x&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;square&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;   &lt;span class="c1"&gt;// 9&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;       &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;첫번째 줄의 &lt;code&gt;square&lt;/code&gt;는 인자 1개를 &lt;code&gt;x&lt;/code&gt;라는 이름으로 받아 &lt;code&gt;x * x&lt;/code&gt;를 리턴하는 함수입니다.&lt;br&gt;
두번째 줄의 &lt;code&gt;result&lt;/code&gt;는 인자를 받지 않고 &lt;code&gt;square 3&lt;/code&gt;을 리턴하는 함수입니다.&lt;br&gt;
세번째 줄의 &lt;code&gt;a&lt;/code&gt;는 인자를 받지 않고 &lt;code&gt;3&lt;/code&gt;을 리턴하는 함수입니다.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;square&lt;/code&gt;는 누가 봐도 함수라고 생각하겠지만, &lt;code&gt;result&lt;/code&gt;와 &lt;code&gt;a&lt;/code&gt;는 변수가 아닌가? 라는 생각이 드실 겁니다. 하지만 이들 또한 인자가 없고 해당 값을 리턴하는 함수로 봐야 함수형 언어를 쉽게 이해할 수 있습니다.&lt;/p&gt;

&lt;p&gt;또한 모든 것이 함수로 취급되기 때문에, 함수 뒤에 별다른 연산식 없이 값만 나열된 것은 자연히 그 함수의 인자로 취급됩니다. 그 때문에 인자를 굳이 &lt;code&gt;()&lt;/code&gt;로 감쌀 필요가 없죠. 물론 우선순위를 바꿔야 할 필요가 있다면 괄호를 써도 상관없습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;square&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// 36&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 코드에서는 &lt;code&gt;a + 3&lt;/code&gt;을 먼저 계산한 뒤 그 값인 &lt;code&gt;6&lt;/code&gt;을 &lt;code&gt;square&lt;/code&gt; 함수에 넘겨줍니다.&lt;/p&gt;

&lt;p&gt;저번 글에서 잠깐 언급했지만, F#을 비롯한 함수형 언어에서는 기본적으로 모든 함수가 immutable입니다.&lt;br&gt;
만일 이미 기존에 존재한 함수에 새 값을 할당하고자 할 경우, 아예 새 메모리를 할당하여 그 값을 바인딩합니다.&lt;br&gt;
이 과정에서 기존에 정의된 값은 가려지기 때문에 다시는 접근이 불가능합니다.&lt;/p&gt;

&lt;p&gt;하지만 F#은 순수한 FP 언어가 아니기 때문에 함수를 mutable하게 만들 수 있는 키워드를 제공합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mutable&lt;/span&gt; &lt;span class="n"&gt;mutableVar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;mutableVar&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;mutableVar&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;    &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;mutable한 함수를 선언하고자 한다면, &lt;code&gt;let mutable&lt;/code&gt;을 사용하면 됩니다. 이렇게 만들어진 mutable 함수는 &lt;code&gt;&amp;lt;-&lt;/code&gt;를 사용해서 값을 변경할 수 있습니다. (&lt;code&gt;=&lt;/code&gt;는 &lt;code&gt;let&lt;/code&gt;으로 바인딩할 때를 제외하면 값이 같은지를 확인하는 함수이므로 여기서 &lt;code&gt;=&lt;/code&gt;를 사용해서는 안 됩니다.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mutable은 그 자체로 FP의 패러다임을 깨기 때문에 사용을 신중하게 고려해야 합니다. 대부분의 상황에서는 mutable 없이도 충분히 구현이 가능합니다.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Primitive Types
&lt;/h3&gt;

&lt;p&gt;위에서 정의한 &lt;code&gt;square&lt;/code&gt; 함수를 보면 인자 &lt;code&gt;x&lt;/code&gt;에 딱히 타입을 정해두지 않은 것을 알 수 있습니다. 하지만 이것이 F#에선 타입이 존재하지 않는다는 것을 의미하진 않습니다. F#은 컴파일 시에 type이 결정되는 Statically Typed Language이며, 강력한 타입 추론을 지원합니다. F#에서 지원하는 primitive type은 다음과 같으며 &lt;code&gt;unit&lt;/code&gt;을 제외하고 전부 .NET에서의 type에 대응됩니다.&lt;br&gt;
(좌측이 F# type, 우측이 .NET type입니다.)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;bool = Bool&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;byte = Byte&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sbyte = SByte&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;int16 = Int16&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;uint16 = UInt16&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;int = Int32&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;uint = UInt32&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;int64 = Int64&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;uint64 = UInt64&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;nativeint = IntPtr&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;unativeint = UIntPtr&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;decimal = Decimal&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;float, double = Double&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;float32, single = Single&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;char = Char&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;string = String&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;unit :&lt;/strong&gt; '값이 없음'을 나타내는 F#만의 타입입니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;C#에서는 &lt;code&gt;float&lt;/code&gt;과 &lt;code&gt;double&lt;/code&gt;이 다르지만, F#에서는 둘 다 동일한 type, 정확히는 &lt;code&gt;double&lt;/code&gt;로 취급됩니다.&lt;br&gt;
또한 C#에서 사용하는 대부분의 연산자 역시 F#에서 동일하게 사용 가능합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;boolean1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;boolean2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;false&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;boolean3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="n"&gt;boolean1&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;boolean2&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="bp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// false&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;string1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;string2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;string3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s2"&gt;"C:&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;Program Files&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;          // @은 F#에서도 verbatim을 뜻합니다.
let string4 = """&lt;/span&gt;&lt;span class="nc"&gt;Triple&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt; &lt;span class="n"&gt;literal&lt;/span&gt;&lt;span class="s2"&gt;"""   // Triple quote도 가능합니다.
let string5 = string1 + "&lt;/span&gt; &lt;span class="s2"&gt;" + string2           // "&lt;/span&gt;&lt;span class="nc"&gt;Hello&lt;/span&gt; &lt;span class="n"&gt;world&lt;/span&gt;&lt;span class="s2"&gt;"
let string6 = string5.[0..6]                // Substring - "&lt;/span&gt;&lt;span class="nc"&gt;Hello&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="s2"&gt;"

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;위에서도 언급했듯이 F#은 타입 추론을 하기 때문에 명시적으로 지정해줄 필요는 없지만, 필요하다면 지정하는 것도 가능합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sampleFunc&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;square&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;다음 글에선 Tuple에 대해 알아보겠습니다.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
    </item>
    <item>
      <title>F# Tutorial (1) - Intro</title>
      <dc:creator>CloudHolic</dc:creator>
      <pubDate>Tue, 03 Jan 2023 02:35:36 +0000</pubDate>
      <link>https://forem.com/cloudholic/f-tutorial-1-intro-a5o</link>
      <guid>https://forem.com/cloudholic/f-tutorial-1-intro-a5o</guid>
      <description>&lt;p&gt;&lt;strong&gt;※ 이 시리즈는 코딩을 처음 하는 사람을 대상으로 하지 않습니다. 이미 기본적인 전산학 및 코딩, 특히 C#과 OOP에 대해서는 이미 알고 있다고 가정하고 진행합니다.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;닷넷하면 보통 C#을 떠올리기 마련이지만, (그리고 실제로도 C#이 주가 되는 환경이기는 하지만) 닷넷 위에서 동작하는 언어가 C#만 있는 것은 아닙니다. Delphi.NET이나 C++/CLI 같은 원본이 따로 있는 언어를 제외하면, VB.NET과 F#이 있습니다. 그리고 이 시리즈에서 살펴볼 언어는 F#입니다.&lt;/p&gt;

&lt;p&gt;F#은 그 이름답게 Functional Programming(FP)을 위한 언어입니다.&lt;br&gt;
그러니 F#을 사용하다 보면 FP 역시 알게 될 수 밖에 없습니다. 마치 C#을 하다보면 OOP를 알게 되는 것처럼요.&lt;/p&gt;

&lt;p&gt;물론 함수형 언어가 F#만 있는 것은 아닙니다. LISP과 여기서 파생된 Scheme, 순수 함수형 언어로 유명한 Haskell, JVM 위에서 돌아가게 만든 Clojure 등등 종류가 생각보다 다양합니다. 이런 언어들과 비교하면 F#은 순수한 함수형 언어는 아닙니다. 함수형 패러다임이 주가 되기는 하지만, 닷넷 및 C#과의 호환성을 위해 class나 mutable, loop 등 순수한 함수형 언어에선 찾아볼 수 없는 문법들이 많죠. 이런 식으로 OOP와 FP를 섞어놓은 언어는 F# 외에도 Scala, Kotlin, Javascript (많은 사람들이 잘 모르지만 Javascript는 multi-paradigm 언어입니다. React에서 쓰는 Functional Component를 생각해보시면 됩니다.) 등이 있습니다. 하지만 이들 언어는 OOP 베이스에 FP를 약간 섞은 식이라면, Scala와 F#은 FP 베이스에 OOP를 약간 섞은 느낌입니다.&lt;/p&gt;

&lt;p&gt;여기서는 FP로써의 F#을 알아볼 것이기 때문에 (얼마 안되지만) OOP적인 요소는 최대한 배제하겠습니다. 그러면 Haskell을 사용하지 왜 F#을 쓰냐고요? 저는 닷넷의 지원을 받는다는게 굉장히 큰 장점이라고 생각합니다. 결국 C#과 F# 모두 CIL로 컴파일되기 때문에 C#과 F#의 상호호환이 상당히 쉽게 가능하고, 무엇보다 F# 또한 패키지 매니저로 nuget을 사용하기 때문에 C#을 해보셨던 분이라면 쉽게 적응할 수 있거든요.&lt;/p&gt;

&lt;p&gt;그러면 C#만 쓰지 왜 F#을 같이 쓰냐고 물을 수 있습니다. FP 언어는 OOP 언어엔 없는 몇 가지 특징들이 있습니다. 추후에 자세히 다루겠지만, FP 언어는 기본적으로 불변성(Immutability)을 지향하며, 함수 그 자체가 일급 객체이기 때문에 코드를 간략하게 쓰기 용이합니다. 또한 언어 자체적으로 Lazy evaluation을 지원하죠. 이러한 특징들 덕에 FP 언어는 유지보수가 쉬우며, 코드를 간략하게 쓰기 용이합니다.&lt;/p&gt;

&lt;p&gt;간단한 예시를 통해 비교해 보죠. 아래 코드는 Quicksort를 수행하는 C#코드입니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QuickSortHelper&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;QuickSort&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IComparable&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;     
        &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;firstElement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;smallerElements&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;largerElements&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;elem&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CompareTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;firstElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         
                &lt;span class="n"&gt;smallerElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         
            &lt;span class="k"&gt;else&lt;/span&gt;         
                &lt;span class="n"&gt;largerElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;QuickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;smallerElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;firstElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;QuickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;largerElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;그리고 이 코드와 동일한 일을 하는 F#코드는 다음과 같습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;rec&lt;/span&gt; &lt;span class="n"&gt;quicksort&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;smaller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;larger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;partition&lt;/span&gt; &lt;span class="o"&gt;((&amp;gt;=)&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;
        &lt;span class="nn"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;concat&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;quicksort&lt;/span&gt; &lt;span class="n"&gt;smaller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt; &lt;span class="n"&gt;quicksort&lt;/span&gt; &lt;span class="n"&gt;larger&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;27줄짜리 코드가 5줄로 줄어들었습니다.&lt;/p&gt;

&lt;p&gt;F#은 이처럼 닷넷에서 사용 가능한 유일한 FP 언어라는 점에서 충분히 매력적인 언어라고 생각합니다. 다음 글에서부터 본격적으로 F#의 문법 및 FP에 대해 알아보겠습니다.&lt;/p&gt;

</description>
      <category>fsharp</category>
    </item>
  </channel>
</rss>
