2012-11-02 24 views
6

Argümanlarından bağımsız bir işleve ilişkin verilerim olduğunda, yerel kapsülleme üzerinden blok kapsüllemeyi ne zaman kullanmalıyım?Blok kapsülleme ve yerel kapsülleme - izin ver

zaman kullanmalıyım:

(let [hello "Hello "] 
    (defn do-greet 
    "Print a greeting." 
    [name] 
    (println (str hello name)))) 

Karşı: Kesinlikle

(defn do-greet 
    "Print a greeting." 
    [name] 
    (let [hello "Hello "] 
    (println (str hello name)))) 

cevap

6

Sözcüksel olarak kapsam dahilindeki bir kod bloğu içindeki değeri sabit bir sabit gibi kullanmak istiyorsanız, ilk seçenek makul bir seçenektir. değeri hesaplamak için pahalı

  • ve
  • değeri, yani fonksiyon çağırmaları
  • karşısında gerçekten sabit bir değişiklik olmayacak, sadece bir kez ad yüklendiğinde yapmak istiyorum: Genellikle eğer böyle bir şey yaptın
  • Değer, çoklu işlev tanımlarında (yani, blok bloğun içine birden fazla yanıt yerleştirdiğinizde) kullanılacaktır.
  • (Muhtemelen?), Çünkü makro genişlemesinin içindeki değeri kullanmak ve makro genişletmenin içine katıştırmak istediğinizde gereksiz karmaşıklık ekler. çeşitli nedenlerden dolayı

ikincisi sürümü muhtemelen en diğer durumlarda tercih edilmelidir, bu iyidir:

  • Bu fonksiyon tanımı üst düzeyde olmasını sağlar daha deyimseldir
    • , kodlayan okunabilirlik/anlama için daha da farklı fonksiyon çağrıları
    • daha Bu yerel bir bağlamda
    • değeri kullanarak amacını yansıtır göre değişebilir değer sağlar
  • +0

    Bunu beğendim, daha fazla puan kaplarsın. Makro genişletme noktanızın geçerli olduğundan emin değilim, çünkü genişlemenin etrafına dolanıp yine de işlevin içinde olabilirsiniz. Okunabilirlik için, stilistik seçimleri anlamsal farklılıklardan ayırmayı öneririm. (Değer, farklı işlev çağırmalarına göre değişebilir). – bmillare

    1

    bu:

    (defn do-greet 
        "Print a greeting." 
        [name] 
        (let [hello "Hello "] 
        (println (str hello name)))) 
    
    2

    hello Eğer yalnızca bu tek fonksiyonu kullanılır, bu daha mantıklı let işlevinin kendisini içine koymak için. Birden çok işlevde hello kullanacaksanız, bu işlevlerin dışında let olması ve bu işlevlerin etrafına sarılması mantıklı olacaktır.

    +0

    İki çalışma zamanında eşdeğer değilse, yalnızca stile dayalı olarak karar vermememiz gerektiğini iddia ediyorum. Bunun yerine bağlamanın statik bir kaynak okuması olduğunu düşünün (([merhaba (slurp (clojure.java.io/resource "merhaba"))] ... '. Sorumu daha genel olarak bıraktım çünkü bu formların gerçekte nasıl değerlendirildiğini ve karşılık gelen dezavantajların ne olduğunu bilmiyorum. – ToBeReplaced

    +1

    Bazı durumlarda stil ile ilgisi yoktur. İki farklı fonksiyonda bulunacak değere ihtiyacınız varsa, bu fonksiyonların kapsamının üzerinde mevcut değeri yapmanız gerekir. Ayrıca, @ amalloy'un cevabına bakınız. – Rayne

    5

    Bu, stilistik bir seçenektir ve muhtemelen, değerin hesaplamanın ne kadar pahalı olduğuna bağlı olarak en azından biraz bağımlı olmalıdır. yerine düşünün:

    (defn nth-prime [n] ...) 
    
    (defn f [x] 
        (let [factor (nth-prime 10000)] 
        (* x factor))) 
    
    (let [factor (nth-prime 10000)] 
        (defn g [x] 
        (* x factor))) 
    

    denir pahalı bir sabiti her zaman f yeniden hesaplanıyor savurgan olduğunu ve g yapıyor önlemek için basit bir teknik kullanır.

    +3

    Çalışma zamanı davranışında (performans) bir farklılık olduğunu söyleyerek, onun stilistik bir seçim olduğunu tartışmayacağım. Sadece askerin örneğinde, pratikte hiçbir fark yoktur, bu stilistiktir. – bmillare

    İlgili konular