2013-10-04 10 views
6

bu geçerlidir: AncakNiçin geçerli bir navlun hedefi olmamalı? Clojure içinde

(loop [a 5] 
    (if (= a 0) 
    "done" 
    (recur (dec a)))) 

bu değildir:

(let [a 5] 
    (if (= a 0) 
    "done" 
    (recur (dec a)))) 

Yani, merak ediyorum: neden döngü vardır ve ayrı izin, aslında verilen her ikisi de (en azından kavramsal olarak) sözcüksel bağlamaları tanıtmak? Öyleyse, neden olmasa da döngü nüks hedef olur?

DÜZENLEME: orijinal olarak yanlış olduğunu fark ettiğim "döngü hedefi" yazdı.

(defn pascal-step [v n] 
    (if (pos? n) 
     (let [l (concat v [0]) 
      r (cons 0 v)] 
     (recur (map + l r) (dec n))) 
     v)) 

Bu işlev, bir m inci hattı ile Pascal üçgeni n+m inci hattı hesaplar:

cevap

5

aşağıdaki örneğe bakalım.

Şimdi, bu let hedefinin recur hedef olduğunu düşünün. Bu durumda pascal-step işlevini let numaralı bağlayıcısından, recur işlecini kullanarak yinelemeli olarak çağıramayacağım.

(defn pascal-line [n] 
    (loop [v [1] 
     i n] 
    (if (pos? i) 
     (let [l (concat v [0]) 
       r (cons 0 v)] 
      (recur (map + l r) (dec i))) 
     v))) 

Şimdi bir pascal üçgeninin n inci hattını hesaplarken ediyoruz:

Şimdi bu örnek biraz daha karmaşık yapalım. Gördüğünüz gibi, hem loop hem de let burada ihtiyacım var.

Bu örnek oldukça basittir, bu nedenle let bağlamayı doğrudan (concat v [0]) ve (cons 0 v) kullanarak kaldırmayı önerebilirsiniz, ancak size yalnızca konsepti gösteriyorum. loop'un içinde let'un kaçınılmaz olduğu daha karmaşık örnekler olabilir.

+1

Tamam, senin noktasını görüyorum. Ancak, niçin yinelenmiyorsa, hangi hedefe atlayacağını belirten ekstra bir isteğe bağlı argüman var mı? Ya da bu, goto'nun yönüne çok fazla gider (ve hepimiz Dijkstra'nın gotolar hakkında ne söylediğini biliyoruz)? – jjpe

+4

@jjpe, döngü olmadığından yinelenen bir hedef değil. Eğer bir tekrarlama hedefi olsaydı, döngü olmazdı. döngü, aynı zamanda, tekrarlanan bir hedef olarak hareket etmesinin dışında, izin verilenle tamamen aynıdır. Http://clojure.org/special_forms#loop adresine bakın. –