摘要:我的目的是確保所有引用的使用都是絕對(duì)安全的,編譯器會(huì)自動(dòng)進(jìn)行檢查。它導(dǎo)致了數(shù)不清的錯(cuò)誤漏洞和系統(tǒng)崩潰,可能在之后年中造成了十億美元的損失。這個(gè)函數(shù)將使用一個(gè)表示我們希望進(jìn)行轉(zhuǎn)換的函數(shù)參數(shù),并返回一個(gè)包含轉(zhuǎn)換結(jié)果的新參數(shù)。
翻譯原文出處:Building a Maybe in JavaScript
鄙人翻譯略差且略有出入,別見笑。
很多時(shí)候我們會(huì)碰到:Uncaught TypeError: Cannot read property "x" of undefined(無法讀取未定義的屬性“x”)。
我猜,如果你正好看到這個(gè)你以前不單只碰過還歷歷在目的東西,可能有那么一刻想把顯示器給砸了。
這里想起了我們尊敬的計(jì)算機(jī)領(lǐng)域的爵士——托尼·霍爾;他在Infoq辦的大會(huì)演講時(shí),用到的主題是:“Null References: The Billion Dollar Mistake”(Null 引用:一個(gè)十億美元級(jí)別的錯(cuò)誤),講演摘要中這樣寫的:
“我把Null引用稱為自己的十億美元錯(cuò)誤。它的發(fā)明是在1965年,那時(shí)我用一個(gè)面向?qū)ο笳Z言( ALGOL W )設(shè)計(jì)了第一個(gè)全面的引用類型系統(tǒng)。我的目的是確保所有引用的使用都是絕對(duì)安全的,編譯器會(huì)自動(dòng)進(jìn)行檢查。但是我未能抵御住誘惑,加入了Null引用,僅僅是因?yàn)閷?shí)現(xiàn)起來非常容易。它導(dǎo)致了數(shù)不清的錯(cuò)誤、漏洞和系統(tǒng)崩潰,可能在之后40年中造成了十億美元的損失。近年來,大家開始使用各種程序分析程序,比如微軟的PREfix和PREfast來檢查引用,如果存在為非Null的風(fēng)險(xiǎn)時(shí)就提出警告。更新的程序設(shè)計(jì)語言比如Spec#已經(jīng)引入了非Null引用的聲明。這正是我在1965年拒絕的解決方案。”
幸運(yùn)的是,我們可以使用一些功能性的編程技術(shù),以清潔、簡(jiǎn)潔和可靠的方式緩解這帶來疼痛。讓我們想象一下,我們要從下面的對(duì)象中提取屬性“c”的值,并附加字符串“is great”。
const a = { b: { c: "fp" } };
我們使用的簡(jiǎn)單方法可能是:
const appendString = (obj) => obj.b.c + " is great"; appendString(a);
這樣的寫法很棒,但可悲的是a對(duì)象并非是一成不變的。因此,我們收回的數(shù)據(jù)有時(shí)會(huì)采取到以下的形式:
const a = { b: {} }; // or const a = {};
當(dāng)這個(gè)時(shí)候我們調(diào)用了appendString函數(shù)時(shí),整個(gè)宇宙將會(huì)爆炸的...
無法讀取未定義的屬性“c”這個(gè)時(shí)候可能要我們對(duì)函數(shù)的傳參進(jìn)行空檢查:
const appendString = (obj) => { if (!obj || !obj.b || !obj.b.c || !) return null; return obj.b.c + " is great"; }
這是有效的,但它看起來很丑陋和很容易出錯(cuò)。我們必須對(duì)傳參進(jìn)行每種類型的對(duì)象定義特定的(正確的)空檢查,這是不是很有趣(復(fù)雜)。
哈哈哈,這個(gè)時(shí)候可能Maybe就派得上場(chǎng)了。
基本上,我們都會(huì)將要構(gòu)建的對(duì)象封裝其值可能為null的概念,并且考慮到隨之而來的復(fù)雜性。在學(xué)習(xí)Elm(一門專注于Web前端的純函數(shù)式語言)之后,我會(huì)在Maybe上的封裝了兩個(gè)概念狀態(tài)Maybe.just和Maybe.nothing。對(duì)于初學(xué)者,我們簡(jiǎn)單地定義一個(gè)返回一個(gè)布爾值的isNothing方法,告訴我們Maybe是否不包含任何內(nèi)容:
const isNullOrUndef = (value) => value === null || typeof value === "undefined"; const maybe = (value) => ({ isNothing: () => isNullOrUndef(value) });
甚至使用一個(gè)簡(jiǎn)單的工廠函數(shù)來創(chuàng)建我們的Maybe - 考慮到往后可能會(huì)添加更多的方法,我們將使用一個(gè)對(duì)象來定義它:
const Maybe = { just: maybe, nothing: () => maybe(null) };
所以現(xiàn)在我們可以這樣做:
const maybeNumberOne = Maybe.just("a value"); const maybeNumberTwo = Maybe.nothing(); maybeNumberOne.isNothing(); // false maybeNumberTwo.isNothing(); // true
一切都很好,但到目前為止還不是很實(shí)用。編程是關(guān)于轉(zhuǎn)換數(shù)據(jù)的,所以我們需要一種改變我們的Maybe的方法 - 一個(gè)map函數(shù)。這個(gè)map函數(shù)將使用一個(gè)表示我們希望進(jìn)行轉(zhuǎn)換的函數(shù)參數(shù),并返回一個(gè)包含轉(zhuǎn)換結(jié)果的新參數(shù)。重要的是,如果maybe不包含任何內(nèi)容,那么該函數(shù)將不會(huì)被應(yīng)用,我們將返回一個(gè)新的maybe.nothing方法。
const maybe = (value) => ({ isNothing: () => isNullOrUndef(value), map: (transformer) => !isNullOrUndef(value) ? Maybe.just(transformer(value)) : Maybe.nothing() });
現(xiàn)在我們可以這樣來調(diào)用maybe實(shí)現(xiàn):
const maybeOne = Maybe.just(5); maybeOne.map(x => x + 1); // Maybe.just(6); const maybeTwo = Maybe.nothing(); maybeTwo.map(x => x + 1) // Maybe.nothing();
關(guān)鍵一點(diǎn)的是maybe.map返回一個(gè)新的maybe,所以我們可以將這些操作鏈接在一起?;氐轿覀儸F(xiàn)在可以做的最初的問題:
const a = { b: { c: "fp" } }; const maybeA = Maybe.just(a) .map(a => a.b) .map(b => b.c) .map(c => c + " is great!");
這里的好處是,如果鏈中的任何步驟返回null,我們?nèi)匀粫?huì)得到結(jié)果Maybe.nothing的結(jié)果,而不是運(yùn)行時(shí)錯(cuò)誤。
好了,在Github上面有個(gè)maybe.js庫: A Maybe monad implementation in JavaScript:
它比Haskell的實(shí)現(xiàn)更加靈活,而且還附帶了一些額外的功能,考慮到
JavaScript的類型系統(tǒng)限制和語言的一般靈活性。
如果你看過我以前發(fā)布的文章柯里化函數(shù),那么你就會(huì)想我們可以弄得比這更好。我們可以創(chuàng)建從對(duì)象中提取命名屬性的高階函數(shù),以及用于追加字符串:
const prop = (propName) => (obj) => obj[propName]; const append = (appendee) => (appendix) = appendee + appendix;
這里可以參考知乎上的JavaScript函數(shù)式編程(一)里面的知識(shí)點(diǎn)。
所以現(xiàn)在我們可以在我們的map鏈?zhǔn)街惺褂眠@個(gè)功能:
const a = { b: { c: "fp" } }; const maybeA = Maybe.just(a) .map(prop("b")) .map(prop("c")) .map(append(" is great!"));
好了,我們現(xiàn)在終于到了這一步, 我們已經(jīng)處理了空檢查,并將其重構(gòu)為point-free形式。接下來需要做的就是使邏輯可重用性;我們想要的是能夠?qū)⑽覀兊墓δ軅鬟f給一個(gè)功能,并應(yīng)用所有步驟,以便我們可以在許多不同的Maybe上重新使用提取器:
const extractor = // what we"re about to make extractor(Maybe.just(a)); // Maybe.just("fp is great")
我們需要的是一個(gè)需要我們的步驟的函數(shù),并且每個(gè)步驟依次調(diào)用我們Maybe.map方法。我們將調(diào)用函數(shù)Maybe.chain,我們可以用reducer來實(shí)現(xiàn):
const Maybe = { just: maybe, nothing: () => maybe(null), chain: (...fns) => (input) => fns.reduce((output, curr) => output.map(curr), input) };
我們現(xiàn)在可以構(gòu)建一個(gè)可以應(yīng)用于maybe的可用功能:
const appendToC = Maybe.chain( prop("b"), prop("c"), append(" is great!") );
并將其用于各種輸入:
const goodInput = Maybe.just({ b: { c: "fp" } }); const badInput = Maybe.just({}); appendToC(goodInput); // Maybe.just("fp is great!") appendToC(badInput); // Maybe.nothing()
雖然我在學(xué)習(xí)Elm之前不習(xí)慣Maybe的價(jià)值觀概念,但是他們?cè)贘avaScript中不想落后啊。如果我們簡(jiǎn)簡(jiǎn)單單地去使用它,就只會(huì)使用到基礎(chǔ)方法而已,所以我們要在它的基礎(chǔ)上添加更多的功能函數(shù)。所以我將在稍后閱讀關(guān)于使用Maybe的后續(xù)文章。
::完畢::
更多閱讀Elm入門實(shí)踐(一)——基礎(chǔ)篇
函數(shù)式編程入門教程
JavaScript函數(shù)式編程(一)
JavaScript函數(shù)式編程(二)
JavaScript函數(shù)式編程(三)
函數(shù)式JavaScript(2):如何打造“函數(shù)式”編程語言?
A Maybe monad implementation in JavaScript
Functional Programming in Javascript
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85182.html
摘要:核心開發(fā)人員大神在開了個(gè),用來征詢社區(qū)對(duì)的建議。而且的工程師并沒有因此止步,他們?cè)谖臋n中又告訴開發(fā)者,不僅僅要把寫到中,也應(yīng)該寫到中。無論怎么使用自定義語法,也不應(yīng)該影響這種好處,即使最終實(shí)現(xiàn)看起來有一些怪異。 React 核心開發(fā)人員 sebmarkbage 大神在 GitHub 開了個(gè) issues,用來征詢社區(qū)對(duì) JSX 2.0 的建議。 showImg(https://segm...
摘要:注意,是叫做,不是。兩款瀏覽器同根同源,它們有著同樣的,但配色不同,由藍(lán)紅綠黃四種顏色組成,而由不同深度的藍(lán)色構(gòu)成。另外是基于的新特性實(shí)現(xiàn)的,所以它的一些執(zhí)行也支持異步操作,效率相對(duì)于來說也提高了。是否響應(yīng)信號(hào),一般是命令,默認(rèn)是。 如果大家對(duì) Python 爬蟲有所了解的話,想必你應(yīng)該聽說過 Selenium 這個(gè)庫,這實(shí)際上是一個(gè)自動(dòng)化測(cè)試工具,現(xiàn)在已經(jīng)被廣泛用于網(wǎng)絡(luò)爬蟲中來應(yīng)對(duì) ...
MindsDB作為一個(gè)開源項(xiàng)目,它旨在將機(jī)器學(xué)習(xí)模型無縫集成到現(xiàn)有的數(shù)據(jù)庫系統(tǒng)中,為用戶提供實(shí)時(shí)的數(shù)據(jù)預(yù)測(cè)能力。這個(gè)項(xiàng)目的創(chuàng)新之處在于,它能夠以簡(jiǎn)單、直觀的方式讓開發(fā)者和非技術(shù)人員都能夠利用AI進(jìn)行數(shù)據(jù)分析和預(yù)測(cè)。 它是根據(jù)企業(yè)數(shù)據(jù)庫定制的AI平臺(tái),使用者可以根據(jù)數(shù)據(jù)庫、矢量存儲(chǔ)和應(yīng)用程序數(shù)據(jù)實(shí)時(shí)創(chuàng)建、提供和微調(diào)模型。簡(jiǎn)介MindsDB 的核心理念是使數(shù)據(jù)庫不僅能夠存儲(chǔ)和檢索數(shù)據(jù),還能基于這些數(shù)據(jù)...
檢查內(nèi)容是否用了ChatGPT,準(zhǔn)確率高達(dá)99.9%!OpenAI又左右互搏上了,給AI生成的文本打水印,高達(dá)99.9%準(zhǔn)確率抓「AI槍手」作弊代寫。其能夠精準(zhǔn)識(shí)別出論文或研究報(bào)告是否由ChatGPT撰寫,甚至能追溯其使用的具體時(shí)間點(diǎn)。它能專門用來檢測(cè)是否用ChatGPT水了論文/作業(yè)。早在2022年11月(ChatGPT發(fā)布同月)就已經(jīng)提出想法了。但是!這么好用的東西,卻被內(nèi)部雪藏了2年,現(xiàn)在都...
摘要:整個(gè)項(xiàng)目簡(jiǎn)單還具有實(shí)用價(jià)值,可作為的實(shí)戰(zhàn)項(xiàng)目學(xué)習(xí)的調(diào)試工具欄。查看文檔自動(dòng)在個(gè)人首頁展示編程時(shí)長的工具。通過學(xué)習(xí)這些前沿的人工智能論文,提前了解在未來更多可能性可以將圖片和視頻轉(zhuǎn)換成漫畫風(fēng)格的工具。興趣是最好的老師,HelloGitHub 讓你對(duì)編程感興趣!簡(jiǎn)介HelloGitHub 分享 GitHub 上有趣、入門級(jí)的開源項(xiàng)目。https://github.com/521xueweihan...
閱讀 1561·2021-11-25 09:43
閱讀 2349·2019-08-30 15:55
閱讀 1472·2019-08-30 13:08
閱讀 2684·2019-08-29 10:59
閱讀 823·2019-08-29 10:54
閱讀 1595·2019-08-26 18:26
閱讀 2555·2019-08-26 13:44
閱讀 2659·2019-08-23 18:36