Local Storage 雖可透過 Web API 的 localStorage.getItem()
讀出,但其並非 Free Function,且若 Key 不存在會回傳 undefined
,這些都不適合 Function Pipeline,Wink-fp 特別包成適合 FP 的 readStorage()
。
Version
macOS Catalina 10.15.6
Wink-fp 1.23.0
Functional
按下 Read Local Storage
會讀出 local storage。
<template>
<div>
<button @click="onRead">Read Local Storage</button>
{{ result }}
</div>
</template>
<script>
import { bind, ifElse, isNil, pipe, always } from 'ramda'
import { create, env } from 'sanctuary'
let { Just, Nothing, fromMaybe } = create ({ checkTypes: false, env })
let readStorage = pipe(
bind(localStorage.getItem, localStorage),
ifElse(isNil, always(Nothing), Just)
)
let onRead = function() {
this.result = pipe(
always('name'),
readStorage,
fromMaybe('')
)()
}
export default {
name: 'App',
data: () => ({
name: 'Sam',
result: ''
}),
methods: {
onRead,
}
}
</script>
14 行
let readStorage = pipe(
bind(localStorage.getItem, localStorage),
ifElse(isNil, always(Nothing), Just)
)
若使用 Web API,讀出 local storage 要使用 localStorage.getItem()
,但這種 API 並非 free function,且若 key 不存在會回傳 undefined
, 這些都不適合 Function Pipeline,因此重新建立 free function 且回傳 Maybe Monad 的 readStorage()
。
- 使用
bind()
從localStorae.getItem()
取出 free function - 使用
ifElse()
處理undefined
,若為undefined
則回傳 Nothing,否則回傳 Just
19 行
let onRead = function() {
this.result = pipe(
always('name'),
readStorage,
fromMaybe('')
)()
}
因為 readStorage()
回傳為 Maybe Monad,因此要使用 fromMaybe()
從 Maybe Monad 內取出,並提供 Nothing 的預設值。
Wink-fp
<template>
<div>
<button @click="onRead">Read Local Storage</button>
{{ result }}
</div>
</template>
<script>
import { pipe, always } from 'ramda'
import { create, env } from 'sanctuary'
import { readStorage } from 'wink-fp'
let { fromMaybe } = create ({ checkTypes: false, env })
let onRead = function() {
this.result = pipe(
always('name'),
readStorage,
fromMaybe('')
)()
}
export default {
name: 'App',
data: () => ({
name: 'Sam',
result: ''
}),
methods: {
onRead,
}
}
</script>
11 行
import { readStorage } from 'wink-fp'
let onRead = function() {
this.result = pipe(
always('name'),
readStorage,
fromMaybe('')
)()
}
readStorage()
實務上經常使用,Wink-fp 已經內建。
readStorage()
String -> Maybe String
localStorage.getItem()
的 free function 與 Maybe 版本
String
:讀取 local storage 的 key
Maybe String
:回傳 Maybe Monad,讀出的 String 包在 Maybe 內
Vue 3
<template>
<button @click="onRead">Read Local Storage</button>
{{ result }}
</template>
<script>
import { ref } from 'vue'
import { pipe, always } from 'ramda'
import { create, env } from 'sanctuary'
import { effect } from 'vue3-fp'
import { readStorage } from 'wink-fp'
let { fromMaybe } = create ({ checkTypes: false, env })
let name = ref('Sam')
let result = ref('')
let onRead = pipe(
always('name'),
readStorage,
fromMaybe(''),
effect(result),
)
let setup = pipe(
always({ name, result, onRead })
)
export default {
name:'App',
setup
}
</script>
18 行
let onRead = pipe(
always('name'),
readStorage,
fromMaybe(''),
effect(result),
)
readStorage()
要在 Vue 3 才能發揮威力。
由於 readStorage()
為 free function,因此可輕易整合進 Function Pipeline 中:
- 使用
always()
K combinator 回傳name
- 使用
readStorage()
讀出 local storage - 使用
fromMaybe()
從 Maybe Monad 取出 String - 使用
effect()
寫入result
reactive model
若使用 Web API 的 localStorae.getItem()
,則根本無法透過 Function Pipeline 組合出 onRead()
。
Conclusion
- Web API 當初是以 OOP 設計,因此與 FP 格格不入,可自己將 Web API 包成 free function 方便 Function Pipeline
- Web API 不少都會回傳
undefined
,建議這類 function 都應該包成 Maybe Monad 後回傳,除了可避免忘記處理undefined
造成 runtime error,也方便在 Function Pipeline 處理 - Free function 與 Maybe 在 Vue 2 看不出威力,但在 Vue 3 因為有了 Composition API,能輕易在 Function Pipeline 內使用 free function 與 Maybe Monad