惰性求值(Clojure描述)

先看一个简单的例子:编程

(defn pinc [n]
  (prn ".")
  (inc n))

定义nums:服务器

(def nums (map pinc [1 2 3]))

REPL没有任何输出.
输入nums:编程语言

nums
"."
"."
"."
=> (2 3 4)

nums才被真正的计算.nums在定义的时候并无被计算,只有在使用的时候才会真正的计算. 函数式编程

许多函数式编程语言都是惰性的.Haskell是彻底惰性,在Clojure中,主要的序列操做像map,reduce,filter,repeatedly都是惰性求值.
例如函数

(def n (pinc 0))
"."
=> #'logic.core/n

上个例子被马上求值由于没有序列的存在.code

无限序列

最多见的惰性求值是无限序列或流.若是咱们想要定义一个list包含全部的质数,这个列表是无穷大的.
若是咱们在C++或其余语言定义了这样一个质数序列,程序将无限的计算下去.若是在Clojure或者Haskell中定义了序列,计算不会马上发生.咱们能够只打印前100个质数.由于惰性求值只计算所须要的部分序列.游戏

游戏服务器

想象咱们须要制做一个游戏服务器,游戏中有许多的怪兽,每一个怪兽都有一个随机生成的物品清单:资源

(defn gen-item []
  {:name "sword"
   :attack (rand-int 100)})
  
(def monster {:name "wolf"
              :level 3
              :inventory (repeatedly 10 gen-item)})

咱们的游戏十分巨大,每秒产生1000个怪物,每一个怪物都随身携带10个随机生成的物品. it

若是非惰性求值,服务器不得不消耗大量的资源在随机生成这些物品上. class

感谢这些序列都是惰性计算!尽管每秒都有1000个怪物被生成,但实际上没有任务物品是被实际产生.这些随机物品被实际的生成仅在玩家查看死亡的怪物装备时才发生! 若是只有50%的怪物被杀死,咱们的服务器就减轻了一半的计算量.感谢惰性求值的威力!

相关文章
相关标签/搜索