2011-10-17 35 views
5

İki parametre alan bir fonksiyon tanımlıyorum - harita ve bir anahtar. Anahtar dediğim zaman haritası parametre ayrışmadefn vs karşılık ayrışması ile ilgili olarak

(defn myfunc [{v k} k] 
    v) 

den başvurulmaktadır: 10

let içinde

Benzer şey::

(let [{v k} {:a 10} k :a] v) 

(myfunc {:a 10} :a) 

Şaşırtıcı sonuç beklendiği üretir

başarısız olur, çünkü k tanımlanmadı. ilk bölüm değerlendirildiğinde, an.

Soruma şudur: Neden ifadelerinde ayrıştırma işlev parametreleri içinde farklı davranır?

cevap

3

bu eşdeğer olsun (kaldırıldı .withMeta malzeme ve yeniden biçimlendirilmiş) defn formu Macroexpanding: Yani burada

(def myfunc 
    (fn* myfunc 
     ([p__11393 k] 
      (let* [map__11394 p__11393 
       map__11394 (if (seq? map__11394) 
           (apply hash-map map__11394) 
           map__11394) 
       v   (get map__11394 k)] 
       v)))) 

biz {v k} haritası ilk yerel bir değişkene p__11393 atanan aslında olduğunu görebilirsiniz. Daha sonra if ifadesi, bu değişkenin aslında bir sıra olup olmadığını ve eğer varsa bir karma haritasına dönüştürdüğünü test eder, aksi halde olduğu gibi bırakır. En önemlisi, 'a atanan değer, adresindeki numaralı haritadan bakıldığında bu durumla karşılaşılır, dolayısıyla bu işlem hatasız çalışır (ayrıca :a haritada bulunmadıysa, get bu durumda nil değerini döndürür). let formu macroexpanding Öte yandan

Ben

(let* 
    [map__11431 
    {:a 10} 
    map__11431 
    (if (seq? map__11431) (apply hash-map map__11431) map__11431) 
    v 
    (get map__11431 k) 
    k 
    :a] 
    v) 

almak ve burada v(get map__11431 k) sonucunu aldığını görebilirsiniz, ama k, henüz bu noktada dolayısıyla hata tanımlı değil.

+0

... – aav

+0

söyleyebilirim Eğer bu fonksiyonun vücudunda yıkımın gerçekleştiğini bilirse, bu şaşırtıcı değildir, dolayısıyla bir hata değildir. Ama bence bu gerçeğin uygun yerlerde daha iyi açıklanabilmesi gerekiyor - eğer doğru bir şekilde hatırlamıyorsam, Clojure neşesini hatırlıyorum, gerçekten buna kapılmıyor. – Paul

+0

onun işe yaramayacağı ilginç (ama şaşırtıcı değil): ([myfunc] [{v k} {k: k1}] v) – aav

0

Bu tam bir cevap değil, ama şu işleri yapar: şimdi soru, bir hata olarak ya bir özellik olarak dikkat edilmesi gereken böyle bir fark olması durumunda olduğu

user=> (defn myfunc [{v k} k] v) 
#'user/myfunc 
user=> (myfunc {:a 10} :a) 
10 
user=> (let [k :a {v k} {:a 10}] v) 
10 
user=> 
+0

bu elbette işe yaracaktır, çünkü * k * başka bir şeyden önce tanımlanmıştır – aav

İlgili konular