2012-11-02 3 views
6

引数に依存しない関数に関連するデータがある場合、ローカルカプセル化よりもブロックカプセル化をいつ優先すべきですか?ブロックカプセル化とローカルカプセル化 -

私が使用する必要があります。

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

対:

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

答えて

6

レキシカルスコープのコードブロック内で静的定数のような値を使用する場合、前者は妥当なオプションです。場合、通常、あなたがこれを行うだろう:値を計算することが高価であり、あなたが名前空間が

  • にロードされたときに値が真に一定で一度だけ、それをやりたい

    • 、つまりは、関数の呼び出し間で変更されません
    • この値は、複数の関数定義間で使用されます(つまり、letブロック内に複数のdefnを置く)
    • マクロ展開内の値を使用してletをマクロ展開自体に組み込むため不要な複雑さが増します。

    後者のバージョンは、おそらく他のほとんどの場合に好まれるべきで、それはいくつかの理由のために良いです:

    • トップレベルに関数定義を可能に
    • より慣用的です、
    • 異なる関数呼び出しで値を変えることができます
    • ローカルコンテキストでの値の使用の意図が反映されています
  • +0

    私はこれが好きです、あなたはより多くのポイントをカバーしています。私はマクロ展開ポイントが有効であるかどうかはわかりません。なぜなら、展開の周りを囲むことができるからですが、まだ関数内にあるからです。読みやすくするために、私は文体の選択肢を意味の違いから切り離すことを提案します。 (値は、さまざまな関数呼び出しによって異なる場合があります)。 – bmillare

    1

    間違いなく、この:

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

    helloが、その1つの機能でのみ使用されている場合は、それがより理にかなっています機能の中にletを入れてください。 helloを複数の関数で使用する場合は、letをそれらの関数の外に置き、それらの関数をラップすることが理にかなっています。

    +0

    実行時に2つが同等でない場合は、スタイルに基づいて決定するべきではないと主張します。代わりに静的リソース '(hello(slurp(clojure.java.io/resource" hello "))] ...)'を読み込むことがバインディングであると想像してください。私は、これらのフォームが実際にどのように評価されているのか、対応するトレードオフが何であるのかわからないので、私の質問をより一般的なものにしました。 – ToBeReplaced

    +1

    実際にはスタイルとは関係ない場合もあります。値を2つの異なる関数で使用できるようにする必要がある場合は、それらの関数の範囲を超えて値を使用可能にする必要があります。また、@ amalloyの答えを見てください。 – Rayne

    5

    これは文体の選択であり、値が計算されるのにどれだけ高価であるかには少なくとも左右されます。代わりに考えてみましょう:

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

    と呼ばれる高価な定数たびfを再計算無駄である、とgはそれを行うことを避けるために簡単なテクニックを使用しています。

    +3

    実行時の動作(パフォーマンス)に違いがあると言うことで、私はそのスタイル上の選択肢ではないと主張します。質問者の例では、それが実質的に違いがないという理由だけで、それは文体です。 – bmillare

    関連する問題