문제

When I have data relevant to a function that is independent of its arguments, when should I favor block encapsulation over local encapsulation?

When should I use:

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

Versus:

(defn do-greet
  "Print a greeting."
  [name]
  (let [hello "Hello "]
    (println (str hello name))))
도움이 되었습니까?

해결책

The former is a reasonable option if you want to use the value like a static constant within a lexically scoped block of code. Typically you would do this if:

  • The value is expensive to compute, and you want to do it only once when the namespace is loaded
  • The value is genuinely constant, i.e. will not change across function invocations
  • The value will be used across multiple function definitions (i.e. you put multiple defns inside the let block)
  • (Possibly?) because you want to use the value inside a macro expansion, and embedding the let inside the macro expansion itself would add unnecessary complexity.

The latter version should probably be preferred in most other cases, it is good for several reasons:

  • It is more idiomatic
  • It allows the function definition to be at the top level, which is better for code readability / comprehension
  • It allows the value to vary on different function invocations
  • It better reflects the intent of using the value in a local context

다른 팁

It's a stylistic choice, and one that should probably depend at least a little on how expensive the value is to compute. Consider instead:

(defn nth-prime [n] ...)

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

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

Recomputing an expensive constant every time f is called is wasteful, and g uses a simple technique to avoid doing it.

If hello is only used in that one single function, it makes more sense to put the let inside the function itself. If you were going to be using hello in multiple functions, it'd make sense to have the let outside of and wrapped around those functions.

Definitely this:

(defn do-greet
  "Print a greeting."
  [name]
  (let [hello "Hello "]
    (println (str hello name))))
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top