2 First-Class Functions and Applicative Programming

Functions as First-Class Things

  • A number can be stored in a variable and so can a function:
  var fortytwo = function() { return 42 };
  • A number can be stored in an array slot and so can a function:
var fortytwos = [42, function() { return 42 }];
  • A number can be stored in an object field and so can a function:
var fortytwos = {number: 42, fun: function() { return 42 }};
  • A number can be created as needed and so can a function:
42 + (function() { return 42 })();
//=> 84
  • A number can be passed to a function and so can a function:
function weirdAdd(n, f) { return n + f() }
weirdAdd(42, function() { return 42 });
//=> 84
  • A number can be returned from a function and so can a function:
return 42;
return function() { return 42 };
_.each(['whiskey', 'tango', 'foxtrot'], function(word) {
 console.log(word.charAt(0).toUpperCase() + word.substr(1));
});
// (console) Whiskey
// (console) Tango
// (console) Foxtrot

JavaScript's Multiple Paradigms

Imperative programming
Programming based around describing actions in detail
Prototype-based object-oriented programming
Programming based around prototypical objects and instances of them
Metaprogramming
Programming manipulating the basis of JavaScript's execution model

Imperative programming

var lyrics = [];
for (var bottles = 99; bottles > 0; bottles--) {
 lyrics.push(bottles + " bottles of beer on the wall");
 lyrics.push(bottles + " bottles of beer");
 lyrics.push("Take one down, pass it around");
 if (bottles > 1) {
 lyrics.push((bottles - 1) + " bottles of beer on the wall.");
 }
 else {
 lyrics.push("No more bottles of beer on the wall!");
 }
}
function lyricsSegment(n) {
  return _.chain([])
    .push(n + "bottles of beer on the wall")
    .push(n + "bottles of beer")
    .push("Take one down, pass it around")
    .tap(function(lyrics) {
      if(n > 1)
        lyrics.push((n - 1) + "bottles of beer on the wall.");
      else
        lyrics.push("No more bottles of beer on the wall!");
    })
    .value();
}

Prototype-based object-oriented programming

var a = {name: "a", fun: function () { return this; }};
a.fun();
//=> {name: "a", fun: ...};
var bFunc = function () { return this };
var b = {name: "b", fun: bFunc};
b.fun();
//=> some global object, probably Window

Metaprogramming

function Point2D(x, y) {
  this._x = x;
  this._y = y;
}
new Point2D(0, 1);
//=> {_x: 0, _y: 1}
function Point3D(x, y, z) {
  Point2D.call(this, x, y);
  this._z = z;
}
new Point3D(10, -1, 100);
//=> {_x: 10, _y: -1, _z: 100}

Applicative Programming

var nums = [1,2,3,4,5];
function doubleAll(array) {
  return _.map(array, function(n) {return n*2});
}

doubleAll(nums);
//=> [2, 4, 6, 8, 10]

function average(array) {
  var sum = _.reduce(array, function(a, b) {return a+b});
  return sum / _.size(array);
}

average(nums);
//=> 3

/* grab only even numbers in nums */
function onlyEven(array) {
 return _.filter(array, function(n) {
 return (n%2) === 0;
 });
}
onlyEven(nums);
//=> [2, 4]
  • _.map calls a function on every value in a collection in turn, returning a collection of the results
  • _.reduce collects a composite value from the incremental results of a supplied with an accumulation value and each value in a collection
  • _.filter calls a predicate function (one returning a true or false value) and grabs each value where said predicate returned true, returning them in a new collection

Collection-Centric Programming

_.map({a: 1, b: 2}, _.identity);
//=> [1,2]
_.map({a: 1, b: 2}, function(v, k) {
  return [k,v];
});
//=> [['a', 1], ['b', 2]]
_.map({a: 1, b: 2}, function(v,k,coll) {
 return [k, v, _.keys(coll)];
});
//=> [['a', 1, ['a', 'b']], ['b', 2, ['a', 'b']]]

Other Examples of Applicative Programming

reduceRight

var nums = [100,2,25];
function div(x,y) {return x/y};

_.reduce(nums, div);
//=> 2

_.reduceRight(nums, div);
//=> 0.125
function allOf(/* funs */) {
 return _.reduceRight(arguments, function(truth, f) {
 return truth && f();
 }, true);
}
function anyOf(/* funs */) {
 return _.reduceRight(arguments, function(truth, f) {
 return truth || f();
 }, false);
}
function T() { return true }
function F() { return false }
allOf();
//=> true
allOf(T, T);
//=> true
allOf(T, T, T , T , F);
//=> false
anyOf(T, T, F);
//=> true
anyOf(F, F, F, F);
//=> false
anyOf();
//=> false

find

_.find(['a', 'b', '3', 'd'], _.isNumber);
//=> 3

reject

_.reject(['a', 'b', 3, 'd'], _.isNumber);
//=> ['a', 'b', 'd']

all

_.all([1, 2, 3, 4], _.isNumber);
//=> true

any

_.any([1, 2, 'c', 4], _.isString);
//=> true

sortBy, groupBy, and countBy

var people = [{name: "Rick", age: 30}, {name: "Jaka", age: 24}];
_.sortBy(people, function(p) { return p.age });
//=> [{name: "Jaka", age: 24}, {name: "Rick", age: 30}]
var albums = [{title: "Sabbath Bloody Sabbath", genre: "Metal"},
 {title: "Scientist", genre: "Dub"},
 {title: "Undertow", genre: "Metal"}];
_.groupBy(albums, function(a) { return a.genre });
//=> {Metal:[{title:"Sabbath Bloody Sabbath", genre:"Metal"},
// {title:"Undertow", genre:"Metal"}],
// Dub: [{title:"Scientist", genre:"Dub"}]}


_.countBy(albums, function(a) {return a.genre});
//=> {Metal: 2, Dub: 1}

Defining a Few Applicative Functions

function cat() {
 var head = _.first(arguments);
 if (existy(head))
 return head.concat.apply(head, _.rest(arguments));
 else
 return [];
}
cat([1,2,3], [4,5], [6,7,8]);
//=> [1, 2, 3, 4, 5, 6, 7, 8]
function construct(head, tail) {
 return cat([head], _.toArray(tail));
}
construct(42, [1,2,3]);
//=> [42, 1, 2, 3]

Data Thinking

var zombie = {name: "Bub", film: "Day of the Dead"};
_.keys(zombie);
//=> ["name", "film"]
_.values(zombie);
//=> ["Bub", "Day of the Dead"]
_.pluck([{title: "Chthon", author: "Anthony"},
 {title: "Grendel", author: "Gardner"},
 {title: "After Dark"}],
 'author');
//=> ["Anthony", "Gardner", undefined]

Summary

  • They can be stored in a variable.
  • They can be stored in an array slot.
  • They can be stored in an object field.
  • They can be created as needed.
  • They can be passed to other functions.
  • They can be returned from functions.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末邻辉,一起剝皮案震驚了整個濱河市值骇,隨后出現(xiàn)的幾起案子移国,更是在濱河造成了極大的恐慌,老刑警劉巖迹缀,帶你破解...
    沈念sama閱讀 212,222評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祝懂,死亡現(xiàn)場離奇詭異,居然都是意外死亡嫂易,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評論 3 385
  • 文/潘曉璐 我一進店門怜械,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人峡扩,你說我怎么就攤上這事障本〗探欤” “怎么了?”我有些...
    開封第一講書人閱讀 157,720評論 0 348
  • 文/不壞的土叔 我叫張陵买置,是天一觀的道長强霎。 經(jīng)常有香客問我,道長轩触,這世上最難降的妖魔是什么家夺? 我笑而不...
    開封第一講書人閱讀 56,568評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮拉馋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘柠逞。我一直安慰自己景馁,他們只是感情好逗鸣,可當(dāng)我...
    茶點故事閱讀 65,696評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著透葛,像睡著了一般卿樱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上繁调,一...
    開封第一講書人閱讀 49,879評論 1 290
  • 那天,我揣著相機與錄音岳遥,去河邊找鬼裕寨。 笑死派继,一個胖子當(dāng)著我的面吹牛捻艳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播讯泣,決...
    沈念sama閱讀 39,028評論 3 409
  • 文/蒼蘭香墨 我猛地睜開眼甲雅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拳锚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,773評論 0 268
  • 序言:老撾萬榮一對情侶失蹤匾荆,失蹤者是張志新(化名)和其女友劉穎杆烁,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體兔魂,經(jīng)...
    沈念sama閱讀 44,220評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,550評論 2 327
  • 正文 我和宋清朗相戀三年构罗,在試婚紗的時候發(fā)現(xiàn)自己被綠了智玻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,697評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡盖彭,死狀恐怖页滚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情逻谦,我是刑警寧澤,帶...
    沈念sama閱讀 34,360評論 4 332
  • 正文 年R本政府宣布贱鼻,位于F島的核電站,受9級特大地震影響症昏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肝谭,卻給世界環(huán)境...
    茶點故事閱讀 40,002評論 3 315
  • 文/蒙蒙 一蛾扇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧坟漱,春花似錦更哄、人聲如沸芋齿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,782評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽栅炒。三九已至庸论,卻和暖如春棒呛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背簇秒。 一陣腳步聲響...
    開封第一講書人閱讀 32,010評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留扛禽,地道東北人皱坛。 一個月前我還...
    沈念sama閱讀 46,433評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像剩辟,于是被迫代替她去往敵國和親往扔。 傳聞我的和親對象是個殘疾皇子熊户,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,587評論 2 350

推薦閱讀更多精彩內(nèi)容

  • **2014真題Directions:Read the following text. Choose the be...
    又是夜半驚坐起閱讀 9,437評論 0 23
  • 3980元嚷堡,在我剛剛完成點擊支付寶的瞬間,這筆錢流入了北京新東方的口袋蝌戒。 是的,從決定考gmat到完成報班拟赊、訂住宿...
    婉琰閱讀 207評論 0 0
  • 愛情里最擔(dān)心的就是 當(dāng)你們吵架鬧矛盾的時候 別人趁虛而入來安慰他來逗他開心 然后讓他認為遇見了比你更好的人粹淋。
    Hilarious閱讀 419評論 0 0
  • 這世間有覺得錢重要的人,可是最終屋匕,只是想和一個能好好說話,說得通的人在一起过吻。不然蔗衡,日日夜夜纤虽,抱著金磚玉瓦,如鯁在喉...
    蘭卡公子閱讀 354評論 0 1
  • Preamble Date: Mon Feb 9 12:59:01 PST 2015 近些時間想要瞭解一些特效L...
    jProvim閱讀 626評論 0 5