維基百科中惰性求值的解釋
惰性求值(Lazy Evaluation),又稱惰性計(jì)算、懶惰求值,是一個(gè)計(jì)算機(jī)編程中的一個(gè)概念,它的目的是要最小化計(jì)算機(jī)要做的工作。它有兩個(gè)相關(guān)而又有區(qū)別的含意,可以表示為“延遲求值”和“最小化求值”,本條目專注前者,后者請(qǐng)參見(jiàn)最小化計(jì)算條目。除可以得到性能的提升外,惰性計(jì)算的最重要的好處是它可以構(gòu)造一個(gè)無(wú)限的數(shù)據(jù)類型。
惰性求值的相反是及早求值,這是一個(gè)大多數(shù)編程語(yǔ)言所擁有的普通計(jì)算方式。
import scala.io.Source.fromFile
val iter: Iterator[String] =
fromFile("sampleFile")
.getLines()
文件迭代器就用到了惰性求值.
用戶可以完全像操作內(nèi)存中的數(shù)據(jù)一樣操作文件,然而文件只有一小部分傳入了內(nèi)存中.
lazy val firstLazy = {
println("first lazy")
1
}
lazy val secondLazy = {
println("second lazy")
2
}?
def add(a:Int,b:Int) = {
a+b
}
//在 scala repl 中的結(jié)果
scala> add(secondLazy,firstLazy)
second lazy
first lazy
res0: Int = 3
res0: Int = 3
second lazy 先于 first lazy輸出了
def firstLazy = {
println("first lazy")
1
}
def secondLazy = {
println("second lazy")
2
}
def chooseOne(first: Boolean, a: Int, b: Int) = {
if (first) a else b
}
def chooseOneLazy(first: Boolean, a: => Int, b: => Int) = {
if (first) a else b
}
chooseOne(first = true, secondLazy, firstLazy)
//second lazy
//first lazy
//res0: Int = 2
chooseOneLazy(first = true, secondLazy, firstLazy)
//second lazy
//res1: Int = 2
對(duì)于非純函數(shù),惰性求值會(huì)產(chǎn)生和立即求值產(chǎn)生不一樣的結(jié)果.
//需要查詢mysql等,可能來(lái)自于一個(gè)第三方j(luò)ar包
def itemIdToShopId: Int => Int ?
var cache = Map.empty[Int, Int]
def cachedItemIdToShopId(itemId: Int):Int = {
cache.get(itemId) match {
case Some(shopId) => shopId
case None =>
val shopId = itemIdToShopId(itemId)
cache += itemId -> shopId
shopId
}
}
//用你的本地mock來(lái)測(cè)試程序
def mockItemIdToSHopId: Int => Int
def cachedItemIdToShopId(itemId: Int): Int ={
cache.get(itemId) match {
case Some(shopId) => shopId
case None =>
val shopId = mockItemIdToSHopId(itemId)
cache += itemId -> shopId
shopId
}
}
//將遠(yuǎn)程請(qǐng)求的結(jié)果作為函數(shù)的一個(gè)參數(shù)
def cachedItemIdToShopId(itemId: Int, remoteShopId: Int): Int = {
cache.get(itemId) match {
case Some(shopId) => shopId
case None =>
val shopId = remoteShopId
cache += itemId -> shopId
shopId
}
}
//調(diào)用這個(gè)函數(shù)
cachedItemIdToShopId(itemId,itemIdToShopId(itemId))
沒(méi)錯(cuò),cache根本沒(méi)有起應(yīng)有的作用,函數(shù)每次執(zhí)行的時(shí)候都調(diào)用了itemIdToShopId從遠(yuǎn)程取數(shù)據(jù)
//改成call by name就沒(méi)有這個(gè)問(wèn)題啦
def cachedItemIdToShopId(itemId: Int, remoteShopId: =>Int): Int = {
cache.get(itemId) match {
case Some(shopId) => shopId
case None =>
val shopId = remoteShopId
cache += itemId -> shopId
shopId
}
}
//調(diào)用這個(gè)函數(shù)
cachedItemIdToShopId(itemId,itemIdToShopId(itemId))
更多建議: