国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > JS > 正文

JavaScript惰性求值的一種實現方法示例

2024-05-06 16:47:43
字體:
來源:轉載
供稿:網友

前言

在學習 Haskell 時,我遇到了這種寫法:

sum (takeWhile (<10000) (filter odd (map (^2) [1..])))

這段代碼的意思是,找出自然整數中小于 10000 的同時是乘方數和奇數的數字,再把這些數加總。由于 Haskell 的懶運算特性,上面的程序并不會立馬生成從 1 到 無限大的自然數列表,而是會等待 takeWhile 指令,再生成符合條件的列表。如果用 JS 來寫,很難寫出這么簡潔高表達性的代碼。一個可能的思路就是寫個 while 循環,然后找到符合條件的數進行加總。這個比較簡單,我就不演示了。

但是如果我們要用高階函數來模擬 Haskell 的寫法,就要想個辦法實現懶運算了。提到懶,首先想到的就是 Iterator 。沒人踢它一腳告訴它 next(),它會一直坐那兒不動的。

現在我們就來用 Iterator 來實現一個懶運算。

首先定義一個生成從 1 到無窮大自然數的 generator :

const numbers = function*() { let i = 1 while (true) { yield i++ }}

由于只有在 generator 執行后生成的 iterable 上執行 next() 方法,yield 才會執行,所以我們要做的主要工作就是實現不同的 next 方法,達到目的。

我們需要先創建一個工廠函數 Lazy,Lazy 封裝了我們的各種目標操作 :

const Lazy = iterator => { const next = iterable.next.bind(iterable) const map = () => {} const filter = () => {} const takeWhile = () => {} return {  next,  map,  filter,  takeWhile, }

我們先實現 map 方法,它會把每次 next 返回的值根據提供的回調函數進行修改:

const map = f => { const modifiedNext = () => { const item = next() const mappedValue = f(item.value) return {  value: mappedValue,  done: item.done, } } const newIter = { ...iterable, next: modifiedNext } return lazy(newIter)}

再定義 filter 方法,它會讓 next 只返回符合判斷條件的值:

const filter = predicate => { const modifiedNext = () => { while (true) {  const item = next()  if (predicate(item.value)) {  return item  } } } const newIter = { ...iterable, next: modifiedNext } return lazy(newIter)}

最后,定義 takeWhile,它會限制 next 執行的條件,一旦條件不滿足,則停止執行 next 并返回歷史執行結果:

const takeWhile = predicate => { const result = [] let value = next().value while (predicate(value)) { result.push(value) value = next().value } return result}

主要的方法都定義完了,現在把它們合并起來:

const Lazy = iterable => { const next = iterable.next.bind(iterable) const map = f => { const modifiedNext = () => {  const item = next()  const mappedValue = f(item.value)  return {  value: mappedValue,  done: item.done,  } } const newIter = { ...iterable, next: modifiedNext } return lazy(newIter) } const filter = predicate => { const modifiedNext = () => {  while (true) {  const item = next()  if (predicate(item.value)) {   return item  }  } } const newIter = { ...iterable, next: modifiedNext } return lazy(newIter) } const takeWhile = predicate => { const result = [] let value = next().value while (predicate(value)) {  result.push(value)  value = next().value } return result } return Object.freeze({ map, filter, takeWhile, next, })}const numbers = function*() { let i = 1 while (true) { yield i++ }}

現在用我們寫的 Lazy 和 numbers 函數來實現文章開頭的 Haskell 代碼:

Lazy(numbers()) .map(x => x ** 2) .filter(x => x % 2 === 1) .takeWhile(x => x < 10000) .reduce((x, y) => x + y)// => 16650

參考:

Lazy Evaluation in JavaScript with Generators, Map, Filter, and Reduce

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 菏泽市| 灯塔市| 阿坝县| 怀宁县| 双峰县| 灵武市| 镇远县| 新巴尔虎左旗| 武川县| 沈丘县| 景泰县| 诸暨市| 策勒县| 依兰县| 浑源县| 茌平县| 昌邑市| 监利县| 嘉定区| 报价| 南宁市| 扶余县| 昂仁县| 茌平县| 马龙县| 高平市| 全南县| 云南省| 汶川县| 南部县| 城口县| 封开县| 治县。| 灵武市| 尚义县| 沭阳县| 松滋市| 北流市| 哈尔滨市| 堆龙德庆县| 扶绥县|