代码之家  ›  专栏  ›  技术社区  ›  Surya

clojure延迟函数执行

  •  12
  • Surya  · 技术社区  · 15 年前

    (defn addresses [person-id]
     ;addresses-retrival )
    
    (defn person [id]
      (merge  {:addresses (addresses id)} {:name "john"}))
    

    在上面的person函数中,我希望地址只能按需检索,就像只按需检索一样

    (:addresses (person 10)) 
    

    (person 10)
    

    我不确定我是不是做对了,因为我对clojure很陌生。

    5 回复  |  直到 15 年前
        1
  •  11
  •   Hassan    10 年前

    你可以用延迟。

    (defn person [id]
      (delay  {:addresses (addresses id) :name "john"})) 
    

    (人员2)将返回延迟的,而不评估任何内容。 要访问内容并计算延迟对象,请使用force或deref(或@)。

    (:addresses @(person 5))
    

    或者,你可以把延迟只放在地址上。

    (defn person [id]
      {:addresses (delay (addresses id)) :name "john"})
    

    哪一个更好取决于你的问题。

    (defn get-address [person]
      @(:address person))
    

    它将得到延迟的地址并强制它。

        2
  •  1
  •   John Lawrence Aspden    15 年前

    至少就序列而言,clojure是相当懒惰的,不需要别人告诉他。

    在这里,将地址检索建模为计数,尝试:

    (defn addresses [person-id]
      (iterate #(do (println %) (inc %)) person-id))
    
    (defn person [id]
      (merge  {:addresses (addresses id)} {:name "john"}))
    
    (def people (map person (range 100)))
    

    到目前为止,它还没有打印任何内容,但如果你说:

    (doall (take 5 (:addresses (nth people 10))))
    

    所以让你的地址查找产生一个延迟序列(map,filter,reduce都可以)

        3
  •  1
  •   Abhinav Sarkar    15 年前

    您可以从 addresses 函数,以后调用时将检索地址。像这样:

    (defn addresses [person-id]
     #(;addresses-retrival))
    
    (defn person [id]
      (merge  {:addresses ((addresses id))} {:name "john"}))
    

    注意比 地址 函数返回一个匿名函数(使用 # person 函数使用一对额外的paren调用匿名函数。

        4
  •  0
  •   Jon    15 年前

    ; Note the use of anonymouns function. #(addresses id)
    (defn person [id] 
      (merge  {:addresses #(addresses id)} {:name "john"}))
    
    ; :addresses returns a function. Evaluate it by wrapping it in another set of parans.
    ((:addresses (person 10)))
    
        5
  •  0
  •   Didier A.    9 年前

    请记住,延迟是被记忆的,因此对地址延迟的连续调用总是会产生与第一次取消延迟时相同的地址。

    (defn addresses [person-id]
      {:home (str (rand-int 100) " Cool St.") :work "1243 Boring St."})
    
    (defn person [id]
      (merge {:addresses (delay (addresses id))} {:name "john"}))
    
    (let [person1 (person 1)]
      (println @(:addresses person1))
      (println @(:addresses person1)))
    

    这将打印:

    {:home 65 Cool St., :work 1243 Boring St.}
    {:home 65 Cool St., :work 1243 Boring St.}
    

    注意家庭住址是如何在延迟的第二个顺序上保持不变的。

    (defn addresses [person-id]
      {:home (str (rand-int 100) " Cool St.") :work "1243 Boring St."})
    
    (defn person [id]
      (merge {:addresses (fn [] (addresses id))} {:name "john"}))
    
    (let [person1 (person 1)]
      (println ((:addresses person1)))
      (println ((:addresses person1))))
    

    这将打印:

    {:home 16 Cool St., :work 1243 Boring St.}
    {:home 31 Cool St., :work 1243 Boring St.}
    

    请注意,在随后的结束通话中,家庭地址是如何不同的。

    所以,如果你 addresses 函数会产生副作用,比如从数据库中获取地址。这些人可以更改他们的地址,并且您希望您的代码始终具有最新的地址,如果延迟对您有效,或者如果函数闭包是更好的选择,请记住这一点。