有些演算法在 Imperative 需使用 do while
實現,在 Ramda 可改用 until()
。
Version
macOS Catalina 10.15.3
VS Code 1.42.1
Quokka 1.0.277
Ramda 0.27.0
Imperative
let f = a => b => c => {
let result = c
do {
result = result * b
} while(result <= a)
return result
}
f(10)(2)(1) // ?
若我們希望某數值每次 乘以 2
,直到 大於 10
才停下來。
Imperative 會使用 do while
,直到 while()
內 expression 為 false
為止。
until()
let until = f1 => f2 => z => {
let result = z
do {
result = f2(result)
} while(!f1(result))
return result
}
let f = a => b => c => until(x => x > a)(x => x * b)(c)
f(10)(2)(1) // ?
我們可將 do while()
抽成 until()
higher-order function,其中前兩個 argument 都是傳入 function。
Ramda
import { until } from 'ramda'
let f = a => b => c => until(x => x > a)(x => x * b)(c)
f(10)(2)(1) // ?
Ramda 已經提供 until()
可直接使用。
until()
(a → Boolean) → (a → a) → a → a
提供 predicate 與 transformation function,直到 predicate 為 true 才停止
a -> Boolean
:predicate,描述停止的條件
a -> a
:transformation function,描述數值如何改變
a
:傳入 data
a
:回傳相同型別 data
Point-free
import { until, gt, multiply, __ } from 'ramda'
let f = a => b => until(gt(__, a), multiply(b))
f(10)(2)(1) // ?
可將 f()
最後一個 c
argument 拿掉,且 until()
內的 callback 也能以 gt()
與 multiply()
產生,使 callback 也 point-free。
useWith()
import { until, gt, flip, multiply, useWith } from 'ramda'
let f = useWith(until,[flip(gt), multiply])
f(10)(2)(1) // ?
也可進一步使用 useWith()
使 f()
完全 point-free。
Conclusion
until()
在實務上較少使用,但若真有do while
需求,可以改用until()
Reference
Ramda, until()
Ramda, gt()
Ramda, multiply()
Ramda, __()
Ramda, useWith()
Ramda, flip()