嵌套 let 的 Clojure 最佳实践
Clojure best practice for nested let
按以下方式使用 Clojure 嵌套 let
是好的做法,还是令人困惑?
(defn a-fun [config]
(let [config (-> config (parse) (supply-defaults))]
;; do something with config
))
我注意到我在与外部世界对话的输入函数中经常有这种 parsing/checking/validating 东西的模式(在本例中是公开 public 函数的 Clojurescript 库,但我也有Compojure路线有同样的感觉)。
是否令人困惑,因为必须了解绑定可见性的规则(不确定确切的措辞是什么)?
惯用的方法是什么?将 config
名称更改为 parsed-config
,将其放在另一个函数中,完全不同?
我会在
时使用这个成语
- 重新绑定是同一种东西
- 您想明确本地绑定取代
全球一。
例如
(defn fact [n]
(loop [n n, answer 1]
(if (pos? n)
(recur (dec n) (* answer n))
answer)))
这也会阻止您意外使用全局绑定,而我很容易这样做。
@Thumbnail 的回答很好,但我个人几乎不会以这种方式将外部绑定与内部绑定重叠。即使您了解绑定规则,并出于充分的理由想要隐藏外部变量,这也会让阅读代码的人感到困惑——稍后,当您忘记代码的工作原理后,这很可能就是您。
假设我有一个复杂的函数,我看到变量 foo
在函数中间的某处使用。我查找并看到它的绑定——可能作为函数参数,这很明显并且很容易注意到。如果我没有注意到下面某处的名称是 rebound,那么我就会误解变量中的内容。
所以我通常会根据代码中不同变量的作用来编造新的相关名称。有时名称差异有些随意。
我认为这些是不隐藏变量的充分理由,我认为@Thumbnail 给出了继续隐藏变量的理由。需要权衡取舍,您必须决定什么最适合您的情况。
短函数可能是更好的阴影上下文。就个人而言,如果我做了这种事情,或者如果我一遍又一遍地做,我会在文件顶部添加一个非常明显的注释。
编辑:正如 nha 的评论让我意识到的那样,当新绑定紧接在前一个绑定之后时,隐藏变量可能更合理;这使得很难忽略名称正在重新定义的事实。
另一种选择是稍微重命名参数,保留 "final" 版本数据的通用名称:
(defn a-fun [config-in]
(let [config (-> config-in (parse) (supply-defaults))]
;; do something with config
))
我有时也使用后缀-arg
、-orig
等来区分处理的各个阶段。
按以下方式使用 Clojure 嵌套 let
是好的做法,还是令人困惑?
(defn a-fun [config]
(let [config (-> config (parse) (supply-defaults))]
;; do something with config
))
我注意到我在与外部世界对话的输入函数中经常有这种 parsing/checking/validating 东西的模式(在本例中是公开 public 函数的 Clojurescript 库,但我也有Compojure路线有同样的感觉)。
是否令人困惑,因为必须了解绑定可见性的规则(不确定确切的措辞是什么)?
惯用的方法是什么?将 config
名称更改为 parsed-config
,将其放在另一个函数中,完全不同?
我会在
时使用这个成语- 重新绑定是同一种东西
- 您想明确本地绑定取代 全球一。
例如
(defn fact [n]
(loop [n n, answer 1]
(if (pos? n)
(recur (dec n) (* answer n))
answer)))
这也会阻止您意外使用全局绑定,而我很容易这样做。
@Thumbnail 的回答很好,但我个人几乎不会以这种方式将外部绑定与内部绑定重叠。即使您了解绑定规则,并出于充分的理由想要隐藏外部变量,这也会让阅读代码的人感到困惑——稍后,当您忘记代码的工作原理后,这很可能就是您。
假设我有一个复杂的函数,我看到变量 foo
在函数中间的某处使用。我查找并看到它的绑定——可能作为函数参数,这很明显并且很容易注意到。如果我没有注意到下面某处的名称是 rebound,那么我就会误解变量中的内容。
所以我通常会根据代码中不同变量的作用来编造新的相关名称。有时名称差异有些随意。
我认为这些是不隐藏变量的充分理由,我认为@Thumbnail 给出了继续隐藏变量的理由。需要权衡取舍,您必须决定什么最适合您的情况。
短函数可能是更好的阴影上下文。就个人而言,如果我做了这种事情,或者如果我一遍又一遍地做,我会在文件顶部添加一个非常明显的注释。
编辑:正如 nha 的评论让我意识到的那样,当新绑定紧接在前一个绑定之后时,隐藏变量可能更合理;这使得很难忽略名称正在重新定义的事实。
另一种选择是稍微重命名参数,保留 "final" 版本数据的通用名称:
(defn a-fun [config-in]
(let [config (-> config-in (parse) (supply-defaults))]
;; do something with config
))
我有时也使用后缀-arg
、-orig
等来区分处理的各个阶段。