Hey Underscore, You're Doing It Wrong! 觀後感

起因


Diro 分享了一個影片


以下簡單記錄我看完的心得

內容簡介


Speaker 是 Brian Lonsdorf (CTO of Loop/Recur, 多麼 geek 的公司名 XD)
LinkedIn: https://www.linkedin.com/in/drboolean
GitHub: https://github.com/DrBoolean

整個影片的重點在說明 Underscore 這個 library 雖然宣稱提供了一些有用的 functional programming helpers, 但是它的介面設計讓使用的人很難寫出真的 functional language 特性的 codes

Currying

以下他用幾個例子來說明 Underscore 的問題
要看以下他舉的例子前, 先說明一個東西 - Currying
假設你有一個 function 叫 add
var add = function(x, y) {
    return x + y;
}
假設你希望可以這樣寫
var add2 = add(2); // return: function()

add2(10); // return: 12
add2(5); // return: 7
那你就要修改一下你的 add 定義
var add = function(x) {
    return function(y) {
        return x + y;
    }
}

var add2 = add(2); // return: function(y) {...}

add2(10); // return: 12
add2(5); // return 7
有更 generic 的作法, 請參考 http://blog.rx836.tw/blog/javascript-currying/
作者也有提到一個幫你把你的 function 轉成 curried function 的 library (wu.js)
所以假設這樣寫會把你的 function 轉成 curried function\
var add = function(x, y) {
    return x + y;
}.autoCurry();
舉幾個實際點的例子 (畢竟 add 有點沒感覺)
var modulo = function(divisor, dividend) {
    return dividend % divisor;
}.autoCurry();

modulo(3, 9); // return: 0

var isOdd = module(2);

isOdd(6); // return: 0
isOdd(7); // return: 1

var filter = function(f, xs) {
    return xs.filter(f);
}.autoCurry();

filter(isOdd, [1, 2, 3, 4, 5]); // return: [1, 3, 5]

var getTheOdds = filter(isOdd);

getTheOdds([1, 2, 3, 4, 5]); // return: [1, 3, 5]

講者提的範例

  • 範例一
var firstTwoLetters = function(words) {
    return _.map(words, function(word) {
        return _.first(word, 2);
    });
};

firstTwoLetters(['jim', 'kate']); // return: ['ji', 'ka']
因為 Underscore 的參數順序是先 array 再 function
所以沒辦法寫得更好
他認為如果 Underscore 能把參數順序顛倒且 API 是 curried functions
就可以寫成這樣
// _.first(n, array) 參數顛倒
var firstTwoLetters = function(words) {
    return _.map(words, _.first(2));
};

// 更進一步, _.map(f, array) 參數顛倒
var firstTwo = _.map(_.first(2));

filterTwo(['jim', 'kate']);
  • 範例二
var sortedPhones = function(users) {
    return _.chain(users)
            .sortBy(function(user) { return user.signup_date; })
            .map(function(user) { return user.phone; })
            .value();
};

sortedPhones(users);
他將其改寫為
var sortedPhones = _.compose(
                    _.map(function(user){ return user.phone; }),
                    _.sortBy(function(useR){ return user.signup_date}));

sortedPhones(users);
更進一步
var dot = function(prop, obj) {
    return obj[prop];
}.autoCurry();

var sortedPhones = _.compose(_.map(dot('phone')),
                            _.sortBy(dot('signup_date')));

sortedPhones(users);

結論

我個人認為, 看完這個影片比看 Functional Javascript 這本書還更能感受 functional language 的特性 XD
不過我也還不是很懂, 大家就一起學習吧


0 comments