點燈坊

失くすものさえない今が強くなるチャンスよ

使用 fromMaybe_ 支援 Nothing 提供 Thunk

Sam Xiao's Avatar 2020-11-09

Sanctuary 的 Maybe 除了提供 fromMaybe 取得 Maybe 內部值外,還另外提供了 fromMaybe_ 接受 Thunk,實務上該如何使用呢 ?

Version

Sanctuary 3.1.0

fromMaybe

import { pipe, mult, map, head, fromMaybe } from 'sanctuary'

let data = []

let fib = n => n <= 1 ? n : fib (n - 2) + fib (n - 1)

let f = pipe ([
  head,
  map (mult (2)),
  fromMaybe (fib (30))
])

f (data) // ?

第 7 行

let f = pipe ([
  head,
  map (mult (2)),
  fromMaybe (fib (30))
])

head 回傳為 Maybe,若為 Nothing Maybe 則回傳 Fibonacci Number。

10 行

fromMaybe (fib (30))

Sanctuary 提供了 frommMaybe 從 Maybe 取出內部值。

fromMaybe
a -> Maybe a -> a
從 Maybe 內部取出值

a:提供 Nothing 預設值

Maybe a:data 為 Maybe

a:回傳 Maybe 內部值

計算 Fibonacci Number 是很耗 CPU 運算,若沒遇到 Nothing,則 fib (30) 就白浪費 CPU 了。

比較理想的方式是傳入 _ -> fib (30),因為是 function,因此 fib (30) 不必求值,等 Nothing 出現時才計算 fib (30),可避免 CPU 無效運算。

maybe000

fromMaybe_

import { thunkify } from 'ramda'
import { pipe, mult, map, head, fromMaybe_ } from 'sanctuary'

let data = []

let fib = n => n <= 1 ? n : fib (n - 2) + fib (n - 1)

let f = pipe ([
  head,
  map (mult (2)),
  fromMaybe_ (thunkify (fib) (30))
])

f (data) // ?

11 行

fromMaybe_ (thunkify (fib) (30))

Sanctuary 另外提供了 frommMaybe_ 支援 Thunk,可用來避免 CPU 無效運算。

使用 thunkifyfib 轉成可回傳 Thunk 的 function。

fromMaybe_
(_ -> a) -> Maybe a -> a
從 Maybe 內部取出值,但支援 Thunk

_ -> a :為 Nothing 的預設值提供 Thunk

Maybe a:data 為 Maybe

a:回傳 Maybe 內部值

fromMaybefromMaybe_ 的差異在於第一個 argument 為 _ -> a,也就是 Thunk,因此 fib (x) 將不會事先運算好才傳進 fromMaybe_,而是只將 _ -> a 傳進 fromMaybe_,因為是 function 不會立即計算 Fibonacci Number,直到真的遇到 Nothing 時才會計算。

maybe001

Conclusion

  • 對於很耗 CPU 的 argument 卻又很少用到,可以改傳入 Thunk,如此不失彈性又可節省 CPU 無謂耗損
  • fromMaybefromMaybe_ 的差異在於對 Nothing 支援 Thunk,實務上用到機會不大,但若真的 Nothing 預設值很耗 CPU,可考慮使用 fromMaybe_

Reference

Sanctuary, fromMaybe_
Ramda, thunkify