Frontend
Functional Programming Concepts - Curry、Compose、Pipe
探討函數式編程中的 Curry、Compose、Pipe 的實作與應用
函數式編程(Functional Programming, FP)中,高階函數是核心概念之一。本文將探討三個重要的函數轉換技巧:Curry、Compose、Pipe,並著重分析它們在現代前端開發中的應用。
概念比較
概念 | 主要用途 | 執行順序 | 實際應用 |
---|---|---|---|
Curry | 參數部分應用 | 依序傳入參數 | API 請求配置 |
Compose | 函數組合 | 從右到左 | 數學運算、資料轉換 |
Pipe | 資料流處理 | 從左到右 | 表單處理、API 資料流 |
實作與範例
Curry (柯里化)
type Curry<T extends (...args: any[]) => any> =
T extends (arg: infer A, ...args: infer R) => infer O
? R extends []
? T
: (arg: A) => Curry<(...args: R) => O>
: never;
// 實際應用:API 請求配置
const fetchFromAPI = curry((baseURL: string, endpoint: string, id: string) =>
fetch(`${baseURL}${endpoint}/${id}`)
);
const fetchFromMyAPI = fetchFromAPI('https://api.example.com');
const fetchUser = fetchFromMyAPI('/users');
Compose 與 Pipe
特性 | Compose | Pipe |
---|---|---|
執行順序 | 從右到左 (f(g(x))) | 從左到右 (x → g → f) |
數學概念 | 符合數學函數組合 | 符合資料流處理 |
可讀性 | 需要從內到外閱讀 | 符合直覺閱讀順序 |
適用場景 | 數學運算、純函數組合 | 資料處理流程、事件處理 |
// Compose 示例
const processData = compose(
formatOutput, // 3. 格式化
validateData, // 2. 驗證
normalizeInput // 1. 標準化
);
// Pipe 示例
const processData = pipe(
normalizeInput, // 1. 標準化
validateData, // 2. 驗證
formatOutput // 3. 格式化
);
工具結合
與 RxJS 的結合
// 搜尋功能實作
const searchInput$ = fromEvent<InputEvent>(searchInput, 'input').pipe(
map(event => (event.target as HTMLInputElement).value),
debounceTime(300),
distinctUntilChanged(),
switchMap(async (term) => {
const response = await fetch(`/api/search?q=${term}`);
return response.json();
})
);
常見應用場景
場景 | 推薦方案 | 原因 |
---|---|---|
表單處理 | Pipe + RxJS | 清晰的資料流、方便的異步處理 |
API 資料處理 | Pipe | 直觀的轉換流程 |
配置管理 | Curry | 靈活的參數應用 |
數學計算 | Compose | 符合數學直覺 |
選擇方向
考量面向 | 建議選擇 | 說明 |
---|---|---|
團隊經驗 | Pipe | 最直觀、容易理解 |
資料處理 | Pipe + RxJS | 強大的資料流處理能力 |
函數組合 | Compose | 符合 functional programming 的特性 |
配置管理 | Curry | 靈活的參數管理 |
總結
在日常開發中:
- Pipe 因爲比較直觀所以比較常見一些
- 結合 RxJS 能夠處理複雜的非同步資料流
- Curry 和 Compose 在特定場景下也是有幫助,但需要謹慎使用,建議盡可能跟團隊有共識,避免過度使用,導致程式碼難以閱讀
Last updated on