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))))
4

4 に答える 4

6

レキシカルスコープのコードブロック内で静的定数のような値を使用したい場合、前者は妥当なオプションです。通常、次の場合にこれを行います。

  • 値の計算にはコストがかかり、名前空間が読み込まれたときに一度だけ実行したい
  • 値は完全に一定です。つまり、関数呼び出し間で変化しません。
  • 値は複数の関数定義で使用されます (つまり、let ブロック内に複数の定義を配置します)。
  • (おそらく?)マクロ展開内で値を使用したいため、マクロ展開自体の内部に let を埋め込むと、不要な複雑さが追加されます。

後者のバージョンは、おそらく他のほとんどの場合に優先されるべきであり、いくつかの理由で適切です。

  • それはより慣用的です
  • 関数定義を最上位に配置できるため、コードの読みやすさ/理解が向上します。
  • 異なる関数呼び出しで値を変えることができます
  • ローカルコンテキストで値を使用する意図をよりよく反映しています
于 2012-11-03T04:21:06.770 に答える
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、単純な手法を使用してそれを回避します。

于 2012-11-02T20:49:55.617 に答える
2

がその単一の関数でのみ使用される場合は、関数自体の内部helloに配置する方が理にかなっています。let複数の関数で使用する場合は、それらの関数の外側をラップしhelloて配置するのが理にかなっています。let

于 2012-11-02T20:07:08.650 に答える
1

間違いなくこれ:

(defn do-greet
  "Print a greeting."
  [name]
  (let [hello "Hello "]
    (println (str hello name))))
于 2012-11-02T19:14:02.067 に答える