欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript惰性求值的一種實(shí)現(xiàn)方法示例

 更新時(shí)間:2019年01月11日 10:26:25   作者:Lambda Academy  
這篇文章主要給大家介紹了關(guān)于JavaScript惰性求值的一種實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

在學(xué)習(xí) Haskell 時(shí),我遇到了這種寫(xiě)法:

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

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

但是如果我們要用高階函數(shù)來(lái)模擬 Haskell 的寫(xiě)法,就要想個(gè)辦法實(shí)現(xiàn)懶運(yùn)算了。提到懶,首先想到的就是 Iterator 。沒(méi)人踢它一腳告訴它 next(),它會(huì)一直坐那兒不動(dòng)的。

現(xiàn)在我們就來(lái)用 Iterator 來(lái)實(shí)現(xiàn)一個(gè)懶運(yùn)算。

首先定義一個(gè)生成從 1 到無(wú)窮大自然數(shù)的 generator :

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

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

我們需要先創(chuàng)建一個(gè)工廠函數(shù) Lazy,Lazy 封裝了我們的各種目標(biāo)操作 :

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

我們先實(shí)現(xiàn) map 方法,它會(huì)把每次 next 返回的值根據(jù)提供的回調(diào)函數(shù)進(jìn)行修改:

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 方法,它會(huì)讓 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,它會(huì)限制 next 執(zhí)行的條件,一旦條件不滿足,則停止執(zhí)行 next 并返回歷史執(zhí)行結(jié)果:

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

主要的方法都定義完了,現(xiàn)在把它們合并起來(lái):

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++
 }
}

現(xiàn)在用我們寫(xiě)的 Lazy 和 numbers 函數(shù)來(lái)實(shí)現(xiàn)文章開(kāi)頭的 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

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

最新評(píng)論