惰性求值(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%的怪物被殺死,咱們的服務器就減輕了一半的計算量.感謝惰性求值的威力!

相關文章
相關標籤/搜索