Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Currying vs Partial application #2

Open
JeffKko opened this issue Jul 31, 2018 · 0 comments
Open

Currying vs Partial application #2

JeffKko opened this issue Jul 31, 2018 · 0 comments

Comments

@JeffKko
Copy link
Owner

JeffKko commented Jul 31, 2018

柯里化和部分函數應用

基本函式

function sum(a, b, c) {
  return a + b + c
}

sum(1, 2, 3)  // 6

函式的 length

函式的 length 是參數的數量, 此數值是固定不變的

function test(a, b, c) {
  console.log(test.length)
}

test(1, 2)        // 3
test(1, 2, 3, 4)  // 3

柯里化

Currying(柯里化) 是把一个接受 N 个参数的函数转换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。也就是说每个函数都接受1个参数。

我們可以把 function add 做一個簡單的柯里化

function curriedAdd(a) {
  return function(b) {
    return function(c) {
      return a + b + c
    }
  }
}

curriedAdd(1)(2)(3) // 6

高階柯里化

...

部分函數應用

部分應用程式
部分應用程式將一個函式的
f:X * Y -> R
第一個參數固定來產生新的函式
f’:Y -> R
f' 和 f 不同,只需要填寫第二個參數,這也是為什麼 f' 比 f 少一個參數的原因。

function add 的部分函數應用

function add5(a, b) {
  return 5 + a + b
}

add5(1, 2)  // 8
add5(2, 3)  // 10

效能測試

使用 benchmark 進行效能測試

幾乎沒有複雜運算的情況

sum(1, 2, 3)

結果:

ops/sec 表示每秒可以運算這個函式的次數

normal x 31,078,534 ops/sec ±1.22% (78 runs sampled)
partail application x 14,939,135 ops/sec ±3.70% (79 runs sampled)
curry x 13,758,207 ops/sec ±1.09% (88 runs sampled)

有複雜運算

function sum(a, b, c) {
  return a + b + c
}

// 模擬一個複雜計算的函式, 從 1 加到 10000
function hardFunc() {
  let num = Array.from({length: 10000})
  return num.map((value, index) => index).reduce((a, value) => a + value)
}

function curry(a) {
  return function(b) {
    return function(c) {
      return a + b + c
    }
  }
}

const sumPartial = sum.bind(null, hardFunc()) // partail
const sumCurried = curry(hardFunc()) // curry
  • normal

    sum(hardFunc(), 2, 3)
  • partail application

    sumPartial(2, 3)
  • curry

    sumCurried(2)(3)

結果:

normal x 80.08 ops/sec ±3.08% (66 runs sampled)
partail application x 20,190,427 ops/sec ±1.35% (84 runs sampled)
curry x 17,426,307 ops/sec ±1.20% (85 runs sampled)

可以看到不管是 partial application 或 curry 效能都比基本用法好上幾十萬倍, 計算越複雜,差距會越大

有複雜運算但改為二元函式

sum(hardFunc(), 2)

結果:

normal x 62.09 ops/sec ±3.28% (57 runs sampled)
partail application x 17,972,102 ops/sec ±1.00% (85 runs sampled)
curry x 44,001,782 ops/sec ±1.63% (79 runs sampled)

此次結果 curry 大獲全勝

結論

在 Functional programming 中, 依照不同情況,適當的使用 currying 或 partial application 對優化程式是很有幫助的

參考

此篇文章所有的benchmark測試

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant