顯示具有 FP 標籤的文章。 顯示所有文章
顯示具有 FP 標籤的文章。 顯示所有文章

2017年1月2日 星期一

Function Composition

由多個小 function 組合成大 function


var john = new User("John", "Doe");
string EmailTo(User u) => Domain(FullName(u));

var email = EmailTo(john);

Console.WriteLine(email);
// jodo@gmail.com (姓 2 碼 + 名 2 碼 + gmail.com)

EmailFor() 能根據 User 的 姓 與 名 自動產生 email

string EmailTo(User u) => Domain(FullName(u));

EmailTo() 為 Local Function 由 FullName() 與 Domain() 組合出新的 EmailTo()

這就是所謂的 Function Composition

Function Composition 重複使用性高,程式碼必須『由右而左』

一般人『由左至右』的閱讀習慣,改用 Function Pipeline


namespace ConsoleApp
{
    
    public static class Email
    {
        public static string FullName(this User u) => ShortName(u.FirstName) + CutName(u.LastName);

        public static string Domain(this string localPart) => $"{localPart}@gmail.com";
        private static string ShortName(string s) => s.Substring(0, 2).ToLower();
    }
}


將 Name() 與 Domain() 的第一個參數都改加上 this,變成為 Extension Method


namespace ConsoleApp
{
    internal static class Program
    {
        private static void Main()
        {
            var email = 
                new User("John", "Doe")
                    .FullName()
                    .Domain();
            
            Console.WriteLine(email);
        }
    }
}

原本的 EmailTo() Local Function 就不需要了
只要將 User new 後,直接用 FullName() 與 Domain(),維持了『由左至右』的閱讀習慣

只要將第一個參數加上 this 修飾成為 Extenstion Method 後,
就可由 Function Composition 改成 Function Pipeline 風格

Function Composition 與 Function Pipeline 講的是同一件事情,
只是 Function Composition 採用 由右至左,
而 Function Pipeline 符合閱讀習慣,採用 由左至右

Funciton Compostion 與 Function Pipeline 是 FP 關鍵部分,
以前總以為 C# 沒有支援,
因此無法使用 C# 寫 FP,
有了 Extension Method,
C# 就能很輕鬆的實踐 FP

Extension Method

目的:
讓我們在不修改原始程式,為類別增加新函式。



Enumerable.Range(1, 3)
          .Select(x => x * 2)
          .ToList()
          .ForEach(x => Console.WriteLine(x.ToString()));


Enumerable.Range() 產生 1、2、3
Select() 2、4、6
ForEach() 列印在畫面上

因為 List 才有 ForEach()
所以先 ToList()
再 ForEach()

這邊可以利用 Extension Method
幫 IEnumerable 打造一個 ForEach()




namespace ConsoleApp
{
    public static class Extensions
    {
        internal static void ForEach<t>(this IEnumerable<t> source, Action<t> action)
        {
            foreach (T element in source)
                action(element);
        }
    }
}


整理一下
第一、第一個參數 this IEnumerable 特別加了 this 且 class 或 interface
第二、Extension Method 必須都為 static method




Enumerable
          .Range(1, 3)
          .Select(x => x * 2)
           .ForEach(x => Console.WriteLine(x.ToString()));


用了 Extension Method 後這樣就能拿掉 ToList()

Visual Studio 2017/2019 推薦的擴充功能與更新

參考文章: 覺得 Google 的 Blogger 不太順手?透過 HTML 的 iframe 移花接木 HackMD