成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

基于JavaScript的一些函數(shù)式編程概念講解

scola666 / 3219人閱讀

摘要:以此類推,不定參數(shù)的方程也就被稱為可變參數(shù)函數(shù)。一般來(lái)說(shuō),函數(shù)式編程中的值都被認(rèn)為是不可變值。實(shí)現(xiàn)了函數(shù)的對(duì)象,即可以與其他對(duì)象進(jìn)行對(duì)比判斷是否屬于同一類型,被稱為。半群一個(gè)擁有,即將另一個(gè)對(duì)象轉(zhuǎn)化為相同類型的函數(shù),函數(shù)的對(duì)象稱為。

原文地址
譯者的Github 系列文章地址
本文原作者尚未全部完成,有興趣的可以到原文或者譯文地址關(guān)注更新

Functional Programming Jargon:函數(shù)式編程術(shù)語(yǔ)解釋

本文的主要目的即是希望能夠有一種通俗易懂的方式來(lái)闡述函數(shù)式編程中常見(jiàn)的理論術(shù)語(yǔ)概念

Arity:參數(shù)數(shù)目

Arity代指一個(gè)函數(shù)的參數(shù)數(shù)量,該關(guān)鍵字來(lái)源于類似于unary、binary、ternary等等,由兩個(gè)后綴-ary-ity組成。譬如,如果一個(gè)函數(shù)允許輸入兩個(gè)參數(shù),那就稱為所謂的binary function(二元函數(shù)),或者一個(gè)有兩個(gè)參數(shù)的函數(shù)。有時(shí)候這種函數(shù)也會(huì)被喜歡拉丁語(yǔ)法的人稱為"dyadic(二價(jià)的)"函數(shù)。以此類推,不定參數(shù)的方程也就被稱為variadic(可變參數(shù)函數(shù))。

const sum = (a, b) => a + b;

const arity = sum.length;
console.log(arity);
// => 2
// The arity of sum is 2
Higher-Order Functions (HOF):高等函數(shù)

一個(gè)接收某個(gè)函數(shù)作為參數(shù)的函數(shù)成為高等函數(shù),該函數(shù)可以選擇返回一個(gè)函數(shù)也可以返回其他類型

const filter = (pred, xs) => {
  const result = [];
  for (var idx = 0; idx < xs.length; idx += 1) {
    if (pred(xs[idx])) {
      result.push(xs[idx]);
    }
  }
  return result;
};
const is = type => x => Object(x) instanceof type;
filter(is(Number), [0, "1", 2, null]); //=> [0, 2]
Partial Application:局部封裝

將原本一個(gè)多參數(shù)值的函數(shù)封裝為固定參數(shù)數(shù)目的函數(shù)的過(guò)程稱為Partial Application

let sum = (a, b) => a + b;

// partially applying `a` to `40`
let partial = sum.bind(null, 40);

// Invoking it with `b`
partial(2); //=> 42
Currying

將一個(gè)N參數(shù)值的函數(shù)轉(zhuǎn)化為N個(gè)一元函數(shù)的組合,Currying與Partial Application的區(qū)別在于Partial Application最終生成的函數(shù)允許接收多個(gè)值,而Currying生成的函數(shù)序列中的每個(gè)函數(shù)只允許接收一個(gè)參數(shù)

let sum = (a, b) => a + b;

let curriedSum = (a) => (b) => a + b;

curriedSum(40)(2) // 42.
Composition:組合

感覺(jué)有點(diǎn)像設(shè)計(jì)模式里的Decorator,即能夠?qū)蓚€(gè)指定類型組合轉(zhuǎn)化為一個(gè)新值的函數(shù)

最常見(jiàn)的組合即是常見(jiàn)的函數(shù)組合,允許你將不同的函數(shù)組合成一個(gè)返回單值的函數(shù)

const compose = (f, g) => a => f(g(a)) // Definition
const floorAndToString = compose((val)=> val.toString(), Math.floor) //Usage
floorAndToString(121.212121) // "121"
Purity:純函數(shù)

一個(gè)沒(méi)有任何副作用,并且返回值只由輸入決定的函數(shù)成為純函數(shù)

let greet = "yo";

greet.toUpperCase(); // YO;

greet // yo;

As opposed to:

let numbers = [1, 2, 3];

numbers.splice(0); // [1, 2, 3]

numbers // []
Side effects:副作用

如果一個(gè)函數(shù),除了返回值之外,還會(huì)修改某些其它狀態(tài),或者與外部函數(shù)等有可觀測(cè)的交互

console.log("IO is a side effect!");
Idempotency:冪等性

多次執(zhí)行下都不會(huì)產(chǎn)生副作用的函數(shù)被稱為具有冪等性的函數(shù)

f(f(x)) = f(x)

Math.abs(Math.abs(10))

Point-Free Style

那些并沒(méi)有線性定義參數(shù)的函數(shù)風(fēng)格被稱為Point-Free Style,這類型往往需要currying 或者 Higher-Order functions。

// Given
let map = fn => list => list.map(fn);
let add = (a, b) => a + b;

// Then

// Not points-free - `numbers` is an explicit parameter
let incrementAll = (numbers) => map(add(1))(numbers);

// Points-free - The list is an implicit parameter
let incrementAll2 = map(add(1));

incrementAll明確規(guī)定了參數(shù)numbers, 而incrementAll2是對(duì)于參數(shù)的封裝,并沒(méi)有顯性說(shuō)明numbers參數(shù),因此它可以被稱為Points Free。一般來(lái)說(shuō),Points-free的函數(shù)都不會(huì)用常見(jiàn)的function或者=>關(guān)鍵字來(lái)定義。

Contracts 暫無(wú) Guarded Functions 暫無(wú) Categories:分類

關(guān)聯(lián)到遵循某些規(guī)則的函數(shù)的對(duì)象,譬如monoid

Value:值

計(jì)算中常用到的一些復(fù)合值(complex)或者簡(jiǎn)單值(primitive),包括函數(shù)。一般來(lái)說(shuō),函數(shù)式編程中的值都被認(rèn)為是不可變值。

5
Object.freeze({name: "John", age: 30}) // The `freeze` function enforces immutability.
(a) => a

注意,譬如Functor, Monad這樣包含其他值的結(jié)構(gòu)體本身也是值,這就是說(shuō),這些復(fù)合值也可以相互包含。

Constant:常量

對(duì)于一個(gè)值的不可變引用,不能跟變量相混淆。Variable即指那些可能在任意點(diǎn)唄更改的引用。

const five = 5
const john = {name: "John", age: 30}

常量一般認(rèn)為是透明的,也就是說(shuō),它們可以被值本身代替而不影響最終的計(jì)算結(jié)果,上面的兩個(gè)常量也可以用下述方式表述:

john.age + five === ({name: "John", age: 30}).age + (5)

上述表達(dá)式會(huì)一直返回真。

Functor

Functor即指那些可以引用map函數(shù)的對(duì)象,JavaScript中最簡(jiǎn)單的函數(shù)就是Array。

[2,3,4].map( n => n * 2 ); // [4,6,8]

假設(shè)func構(gòu)造為一個(gè)實(shí)現(xiàn)了map函數(shù)的對(duì)象,fg則是任意的函數(shù),只要func遵循以下規(guī)則就可以將func稱為一個(gè)functor:
Let func be an object implementing a map function, and f, g be arbitrary functions, then func is said to be a functor if the map function adheres to the following rules:

func.map(x => x) == func

以及

func.map(x => f(g(x))) == func.map(g).map(f)

我們將Array稱為Functor,也是因?yàn)樗裱艘韵乱?guī)則:

[1, 2, 3].map(x => x); // = [1, 2, 3]

以及

let f = x => x + 1;
let g = x => x * 2;

[1, 2, 3].map(x => f(g(x))); // = [3, 5, 7]
[1, 2, 3].map(g).map(f);     // = [3, 5, 7]
Pointed Functor

實(shí)現(xiàn)了of方法的Functor,Of會(huì)將任何單值轉(zhuǎn)化為一個(gè)Functor

Pointed Functor在Array中的實(shí)現(xiàn)為:

  Array.prototype.of = (v) => [v];
  
  [].of(1) // [1]
Lift

Lift很類似于map,不過(guò)它可以用于多個(gè)Functors:

在單值函數(shù)下,Map與Lift的作用是一致的:

lift(n => n * 2)([2,3,4]); // [4,6,8]

而Lift可以允許輸入多個(gè)值:

lift((a, b)  => a * b)([1, 2], [3]); // [3, 6]
Referential Transparency:透明引用

一個(gè)可以直接用其值來(lái)替換而不會(huì)影響到程序表現(xiàn)的表達(dá)式稱為透明引用

譬如我們有一個(gè)叫greet的引用

let greet = () => "Hello World!";
任何對(duì)于greet()的調(diào)用都可以被Hello World!直接替換,因此可以將greet稱為透明引用。 Equational Reasoning

當(dāng)一個(gè)應(yīng)用由表達(dá)式組合而成并且沒(méi)有任何副作用的時(shí)候,該系統(tǒng)可以由部分推導(dǎo)而來(lái)

Lazy evaluation:懶計(jì)算

Lazy evaluation 即是所謂的只有在需要某個(gè)值的時(shí)候才進(jìn)行計(jì)算的機(jī)制。在函數(shù)式語(yǔ)言中,這個(gè)機(jī)制就允許對(duì)于那些近乎無(wú)限的列表進(jìn)行操作。

let rand = function*() {
    while(1<2) {
        yield Math.random();
    }
}
let randIter = rand();
randIter.next(); // Each exectuion gives a random value, expression is evaluated on need.
Monoid:獨(dú)異點(diǎn)

一個(gè)monoid就是與某個(gè)恒等值進(jìn)行組合之后不會(huì)影響現(xiàn)有結(jié)果的數(shù)據(jù)類型

一個(gè)最簡(jiǎn)單的Monoid就是如下所示:

1 + 1; // 2

數(shù)據(jù)類型是number,函數(shù)是+

1 + 0; // 1

恒等式的值是0,將0與任何數(shù)相加并不會(huì)改變值。有時(shí)候,monoid類型進(jìn)行不同的交換操作也不會(huì)影響結(jié)果:

1 + (2 + 3) == (1 + 2) + 3; // true

數(shù)組連接也可以認(rèn)為是一個(gè)monoid:

[1, 2].concat([3, 4]); // [1, 2, 3, 4]

恒等值即是空數(shù)組: []

[1, 2].concat([]); // [1, 2]
Monad

一個(gè)Monad就是擁有of以及chain函數(shù)的對(duì)象。 Chain 類似于 map只不過(guò)它會(huì)扁平化最終求得的嵌套式結(jié)果。

["cat,dog","fish,bird"].chain(a => a.split(",")) // ["cat","dog","fish","bird"]

//Contrast to map
["cat,dog","fish,bird"].map(a => a.split(",")) // [["cat","dog"], ["fish","bird"]]

You may also see of and chain referred to as return and bind (not be confused with the JS keyword/function...) in languages which provide Monad-like constructs as part of their standard library (e.g. Haskell, F#), on Wikipedia and in other literature. It"s also important to note that return and bind are not part of the Fantasy Land spec and are mentioned here only for the sake of people interested in learning more about Monads.

Comonad:余單子

實(shí)現(xiàn)了extractextend函數(shù)的對(duì)象

let CoIdentity = v => ({
    val: v,
    extract: this.v,
    extend: f => CoIdentity(f(this))
})

Extract 可以將值從Functor中吐出來(lái):

CoIdentity(1).extract() // 1

Extend則是會(huì)返回一個(gè)跟Commonad相同值的函數(shù):

CoIdentity(1).extend(co => co.extract() + 1) // CoIdentity(2)
Applicative(可適用的) Functor

一個(gè)Applicative Functor就是一個(gè)實(shí)現(xiàn)了ap函數(shù)的對(duì)象,Ap可以將某個(gè)對(duì)象中的某個(gè)值轉(zhuǎn)化為另一個(gè)對(duì)象中的相同類型的值

[(a)=> a + 1].ap([1]) // [2]
Morphism:態(tài)射

一個(gè)轉(zhuǎn)化函數(shù)

Isomorphism:同態(tài)轉(zhuǎn)換

用不同方式存儲(chǔ)的能夠表明相同數(shù)據(jù)的轉(zhuǎn)換

譬如,一個(gè)二維的數(shù)組可以存儲(chǔ)為數(shù)組:[2,3]或者對(duì)象:{x: 2, y: 3}。

// Providing functions to convert in both directions makes them isomorphic.
const pairToCoords = (pair) => ({x: pair[0], y: pair[1]})

const coordsToPair = (coords) => [coords.x, coords.y]

coordsToPair(pairToCoords([1, 2])) // [1, 2]

pairToCoords(coordsToPair({x: 1, y: 2})) // {x: 1, y: 2}
Setoid

實(shí)現(xiàn)了equals函數(shù)的對(duì)象,即可以與其他對(duì)象進(jìn)行對(duì)比判斷是否屬于同一類型,被稱為Setoid。

下面對(duì)于原型的擴(kuò)充可以將Array變成Setoid。

Array.prototype.equals = arr => {
    var len = this.length
    if (len != arr.length) {
        return false
    }
    for (var i = 0; i < len; i++) {
        if (this[i] !== arr[i]) {
            return false
        }
    }
    return true
}

[1, 2].equals([1, 2]) // true
[1, 2].equals([0]) // false
Semigroup:半群

一個(gè)擁有concat,即將另一個(gè)對(duì)象轉(zhuǎn)化為相同類型的函數(shù),函數(shù)的對(duì)象稱為Semigroup。

[1].concat([2]) // [1, 2]
Foldable:可折疊

實(shí)現(xiàn)了reduce函數(shù),即可以將一個(gè)對(duì)象轉(zhuǎn)化為其他類型的函數(shù),的對(duì)象稱為Foldable對(duì)象。

let sum = list => list.reduce((acc, val) => acc + val, 0);
sum([1, 2, 3]) // 6
Traversable 暫無(wú) Type Signatures:類型簽名

一般來(lái)說(shuō),函數(shù)都會(huì)注釋表明它們的參數(shù)類型和返回值類型

// functionName :: firstArgType -> secondArgType -> returnType

// add :: Number -> Number -> Number
let add = x => y => x + y

// increment :: Number -> Number
let increment = x => x + 1

如果一個(gè)函數(shù)接收其他函數(shù)作為參數(shù),譬如這樣:

// call :: (a -> b) -> a -> b
let call = f => x => f(x)

這里的a, b, c, d表明參數(shù)可以是任意類型,不過(guò)它會(huì)將類型a轉(zhuǎn)化為另一個(gè)類型b,而對(duì)于下面這個(gè)map,它的注釋表明了它會(huì)輸入一個(gè)a類型的列表,然后轉(zhuǎn)化為另一個(gè)包含了b類型的列表。

// map :: (a -> b) -> [a] -> [b]
let map = f => list =>  list.map(f)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/79609.html

相關(guān)文章

  • 深入理解JavaScript

    摘要:深入之繼承的多種方式和優(yōu)缺點(diǎn)深入系列第十五篇,講解各種繼承方式和優(yōu)缺點(diǎn)。對(duì)于解釋型語(yǔ)言例如來(lái)說(shuō),通過(guò)詞法分析語(yǔ)法分析語(yǔ)法樹(shù),就可以開(kāi)始解釋執(zhí)行了。 JavaScript深入之繼承的多種方式和優(yōu)缺點(diǎn) JavaScript深入系列第十五篇,講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 寫(xiě)在前面 本文講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 但是注意: 這篇文章更像是筆記,哎,再讓我...

    myeveryheart 評(píng)論0 收藏0
  • JS程序

    摘要:設(shè)計(jì)模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開(kāi)始接觸的時(shí)候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計(jì)模式必須要先搞懂面向?qū)ο缶幊蹋駝t只會(huì)讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學(xué)習(xí)總結(jié)。知識(shí)只有分享才有存在的意義。 是時(shí)候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...

    melody_lql 評(píng)論0 收藏0
  • JavaScript面向?qū)ο螅╫bject-oriented)編程

    摘要:對(duì)象在中,除了數(shù)字字符串布爾值這幾個(gè)簡(jiǎn)單類型外,其他的都是對(duì)象。那么在函數(shù)對(duì)象中,這兩個(gè)屬性的有什么區(qū)別呢表示該函數(shù)對(duì)象的原型表示使用來(lái)執(zhí)行該函數(shù)時(shí)這種函數(shù)一般成為構(gòu)造函數(shù),后面會(huì)講解,新創(chuàng)建的對(duì)象的原型。這時(shí)的函數(shù)通常稱為構(gòu)造函數(shù)。。 本文原發(fā)于我的個(gè)人博客,經(jīng)多次修改后發(fā)到sf上。本文仍在不斷修改中,最新版請(qǐng)?jiān)L問(wèn)個(gè)人博客。 最近工作一直在用nodejs做開(kāi)發(fā),有了nodejs,...

    JerryZou 評(píng)論0 收藏0
  • 面向?qū)ο?em>的 JavaScript

    摘要:是完全的面向?qū)ο笳Z(yǔ)言,它們通過(guò)類的形式組織函數(shù)和變量,使之不能脫離對(duì)象存在。而在基于原型的面向?qū)ο蠓绞街?,?duì)象則是依靠構(gòu)造器利用原型構(gòu)造出來(lái)的。 JavaScript 函數(shù)式腳本語(yǔ)言特性以及其看似隨意的編寫(xiě)風(fēng)格,導(dǎo)致長(zhǎng)期以來(lái)人們對(duì)這一門(mén)語(yǔ)言的誤解,即認(rèn)為 JavaScript 不是一門(mén)面向?qū)ο蟮恼Z(yǔ)言,或者只是部分具備一些面向?qū)ο蟮奶卣?。本文將回歸面向?qū)ο蟊疽?,從?duì)語(yǔ)言感悟的角度闡述為什...

    novo 評(píng)論0 收藏0
  • JavaScript系列(四) - 收藏集 - 掘金

    摘要:函數(shù)式編程前端掘金引言面向?qū)ο缶幊桃恢币詠?lái)都是中的主導(dǎo)范式。函數(shù)式編程是一種強(qiáng)調(diào)減少對(duì)程序外部狀態(tài)產(chǎn)生改變的方式。 JavaScript 函數(shù)式編程 - 前端 - 掘金引言 面向?qū)ο缶幊桃恢币詠?lái)都是JavaScript中的主導(dǎo)范式。JavaScript作為一門(mén)多范式編程語(yǔ)言,然而,近幾年,函數(shù)式編程越來(lái)越多得受到開(kāi)發(fā)者的青睞。函數(shù)式編程是一種強(qiáng)調(diào)減少對(duì)程序外部狀態(tài)產(chǎn)生改變的方式。因此,...

    cfanr 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<