Arguments Optional

                    

這題主要是要讓傳入的參數能有選擇性(可以單個或多個),不過實作部分牽涉到許多Javascript的細節部分,故會就以下主題進行討論:
What is "Currying function and partial function" in javascript ?
function add(x, y)
{
  return x + y;
}
add(x, y);
  一般我們在寫程式的時候,看到的函數呼叫通常長得像上面那樣function的名稱後面的括弧包含了所有的參數,但在這題卻會遇到在函數名稱後面有多個括號來傳遞參數的用法,這個我們稱之為柯理化會與部分函數應用一起討論-Currying and Partial Functions in JavaScript (看怎麼翻,像微分方程中就稱為偏-名稱(Ex:偏微分方程)),先來談Currying,柯里化就是將函數(多個參數/多元 n-ary)轉換成接收1個參數(arity or unary)的函數,函數執行流程就是先接受1個(少數)參數,然後再返回一個新的函數, 講簡單一點的話,就是「只傳遞給函數一部分參數來調用它,讓它返回一個函數去處理剩下的參數。 你可以一次性地調用 curry 函數,也可以每次只傳一個參數分多次調用。」 ーFranklin Risby教授在JS程式設計指南書中提到,因為柯里化的「傳入一個值,回傳一個值(函數)」的特性,讓我們更容易討論以及對程式碼進行改善(refactor)等等,另一方面也提高函數的再使用性(reusable),這也使得我們下面這種函數多次傳入單一參數的呼叫方式變得可行

  //Make this syntax possible: var a = add(2)(3); //5
  var add = function(x) {
    return function(y) 
    { 
      return x + y;
    };
}
//Make two syntaxes possible: add(2,3);  add(2)(3);
function add(x, y) {
     if (typeof y === "undefined") { // partial
        return function (y) {
              return x + y;
        };
     }
   // full application
   return x + y;
}
  再來,我們要來討論部分函數應用,此如下面範例所示,將一個函數的某個參數固定來產生一個新的函數,Ex:下面的add5()即是將參數x固定為5後產生的新函數
  function add(x, y)
  {
      return x + y;
  }
  function add5(y)
  {
    return 5 + y;
  }
What is "closure" in javascript ?

  再來講的主題跟變數的作用範圍(可視範圍)有關,也就是scope,概念有點像生命週期-變數的存活範圍,能不能在該區存取到(看到)它, scope就是一個變數能觸及到的視野, 在變數的 scope 裡,使用該變數都有效,接下來進入主題closure(中文:閉包),他的概念就是我在函數裡面再定義函數(internal),內部的函數可以使用外面函數定義的變數,這個現象就叫做closure

  function add() { 
      var x = arguments[0], y = arguments[1];//Closure
      if(y === undefined && typeof x === 'number' )       
        return function(y)
               {
                  return (typeof x !== 'number' || typeof y !== 'number') ?  undefined : x + y;
                };
      return (typeof x === 'number' && typeof y === 'number' ) ? x + y : undefined ;
}
add(2,3);
add(2)(3);

Hint

Closure
Arguments object

測試的正確結果

add(2, 3) 应该返回 5。
add(2)(3) 应该返回 5。
add("http://bit.ly/IqT6zt") 应该返回 undefined。
add(2, "3") 应该返回 undefined。
add(2)([3]) 应该返回 undefined。

Solution:

這題就是要依照題目要求,當第1個參數(arguments[0])或第2個參數(arguments[1])的資料型態不是number時,要回傳undefined,然後也要使用currying讓參數可以只傳遞一個參數並且如果傳遞的參數型態不為number也會return undefined,也就是只能讓加法順利的完成,不論給定的instruction/syntax的參數的個數是複數或單一,都要讓該instruction/syntax能夠運行

Application of Currying


  柯里化後的函數,能更好擴充新的功能或程式碼,也就是增加可用性(如果要更精準討論軟體的品質則是以軟體工程的概念來分析(Cohesion, Coupling) ),Currying 原理就是把函數的一部份先配置好,這樣好讓其他函數或功能更好連接以達到上面講的效果,如下面一段程式碼一樣
//Transform element in array int number and time five
//將array中的元素轉成number型態並乘上5倍
function edit(arr, act)
{
  return arr.map(function(emt)
                 { 
                     return parseInt(emt)*act; 
                 });
}
edit(['1', '2', '3'], 5); //[5, 10, 15]
//Transform element in array int number and plus one
//將array中的元素轉成number型態並加1
function edit(arr, act)
{
  return arr.map(function(emt)
                 { 
                     return parseInt(emt)+act; 
                 });
}
edit(['1', '2', '3'], 1); // [2, 3, 4]

//Curry
function edit(arr, action)
{
  return arr.map(function(emt){
                                  return action(parseInt(emt)); 
                  });
}
function multiple(data)
{
  return function(para){ return data * para; };
}
function add(data)
{
  return function(para){ return data + para; };
}
edit(['1', '2', '3'], multiple(5));  //[5, 10, 15]
edit(['1', '2', '3'], add(1));//[2, 3, 4]



**P.S. / Reference:  關於軟體品質分析2個指標-提高內聚(Cohesion)-把功能相關的程式執行時所需要的資料與函數等等集合成一個模組,降低耦合(Coupling/dependency)-模組及模組之間資訊或參數依赖的程度,模組之間是否有傳遞參數或者使用global variable。
          Chapter 4 curry
          為何要柯里化?
          Make this syntax possible
          Make add(1,2) and add(1)(2) both possible
          作用範圍(scope) 與 生命期(lifetime)
          JavaScript中的closure好難懂?
          

results matching ""

    No results matching ""