2013-08-25 179 views
0

我有功能看起來像這樣的:咖喱功能應該如何工作?

function curry(fn) { 
    var args = [].slice.call(arguments, 1); 
    return function() { 
     return fn.call(this, args.concat([].slice.call(arguments))); 
    }; 
} 

我一直以爲這就是函數應該看起來怎麼樣,應該努力爲:

function add(a, b, c, d) { 
    return a+b+c+d; 
} 


curry(add, 1, 2)(3, 4); 

Wikipedia Article

它可以稱爲功能鏈,每個功能都有一個參數

所以咖喱應該是這樣的:

function curry(fn) { 
    var args = []; 
    return function curring() { 
     args = args.concat([].slice.call(arguments)); 
     if (args.length >= fn.length) { 
      return fn.apply(this, args); 
     } else { 
      return curring; 
     } 
    }; 
} 

,並作爲本:

function add(a, b, c, d) { 
    return a+b+c+d; 
} 

curry(add)(1)(2)(3)(4); 

我說得對不對?

+0

我認爲兩者都是正確的。但根據John Resig在「javascript ninja的祕密」中的第一種方法是正確的。 – AhmadF

+0

@AhmadF怎麼回事?第一個返回一個函數,然後返回結果,第二個返回函數,直到列表或參數與函數參數的數量相同。 – jcubic

+0

我想'函數add(a,b,c,d)'必須返回'a + b + c + d'而不是'a + b + c + c'。 – JRL

回答

1

嚴格地說,討好有許多參數的函數轉換成一個系列的每個功能與一個單一的參數,如你的第二個curry功能:

  • 如果你打電話給所有的人(在鏈中),您將得到該函數的完整應用,該函數產生與原始函數相同的結果:
    curry(add)(1)(2)(3)(4)返回的結果與add(1, 2, 3, 4)相同,即10

  • 如果只調用一個子集,你會得到一個部分應用功能:

    1. addOne = curry(add)(1);
    2. addOneAndTwo = addOne(2);
    3. addOneAndTwo(3)(4)返回10

在Javascript中,鑽營被通常用作同義詞米爲部分應用程序,如在您的第一個curry函數。複述Prototype documentation

咖喱咖喱(燒傷)參數的函數,返回一個新的功能,當有電話叫原傳入咖喱參數(與任何新的沿)。

有關更詳細的解釋,請參見What is the difference between currying and partial application

這裏是一個true curry function in javascript作者:Evan Borden的工作實現。

幾個注意事項:

  • 在你的第一個功能,fn.call是錯誤的。您必須使用fn.apply,因爲您作爲第二個參數傳遞的數組必須用作參數列表,並且call將其視爲僅一個參數。

  • 你的第二函數產生咖喱功能,可以調用只有1次,因爲每個稱爲curring實例修改捕獲args陣列中,當curry被稱爲其初始化。

    例如:

    1. addOne = curry(add)(1);限定addOne與自己args初始化爲[1]

    2. addOne(2)(3)(4)返回10和修改args[1, 2, 3, 4]

    3. addOne(2)(3)(4)(第二次)失敗,並addOne(...) is not a function
      addOne(2)試圖調用add(1, 2, 3, 4, 2)

+0

第一個問題只是一個錯誤,它應該適用,但第二個錯誤,謝謝指出。 – jcubic