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