Unit testing Clojure中的单元测试局部函数(letfn)?

Unit testing Clojure中的单元测试局部函数(letfn)?,unit-testing,clojure,scope,tdd,Unit Testing,Clojure,Scope,Tdd,我花了几年的时间做“回到过去”计划,现在正在学习Clojure。Scheme中的一个“最佳实践”是在父函数中定义helper函数,从而限制它们从“外部”的可见性。当然,当时TDD还没有完成(或已知!),所以测试此类函数不是问题 我仍然想用这种方式构造Clojure函数;i、 例如,使用letfn在主函数中绑定辅助函数。当然,测试这种“本地”函数是有问题的。我意识到我可以定义“private”函数,但这限制了名称空间的可见性,这很有帮助,但没有那么细粒度。如果您在另一个函数中遇到一个letfn,很

我花了几年的时间做“回到过去”计划,现在正在学习Clojure。Scheme中的一个“最佳实践”是在父函数中定义helper函数,从而限制它们从“外部”的可见性。当然,当时TDD还没有完成(或已知!),所以测试此类函数不是问题

我仍然想用这种方式构造Clojure函数;i、 例如,使用letfn在主函数中绑定辅助函数。当然,测试这种“本地”函数是有问题的。我意识到我可以定义“private”函数,但这限制了名称空间的可见性,这很有帮助,但没有那么细粒度。如果您在另一个函数中遇到一个letfn,很明显该函数不可用于一般用途

所以,我的问题是,我们可以测试这样的局部函数吗?如果可以,如何测试?如果没有,那么是否有一些约定来帮助代码读取,以便清楚地知道一个函数只有一个调用方

蒂亚,
Bill

通常的方法是将函数放在名称空间中

一种选择是使用元数据:

user=> (defn ^{::square #(* % %)} cube [x]
  #_=>   (* x ((::square (meta #'cube)) x)))
#'user/cube
user=> (meta #'cube)
{…, :user/square #<user$fn__780 user$fn__780@2e62c3f9>}
user=> (cube 3)
27
user=>(defn^{::square#(*%)}cube[x]
#_=>(*x(::正方形(元立方))x)
#'用户/多维数据集
用户=>(元#'立方体)
{…,:user/square}
用户=>(多维数据集3)
27

当然,可以编写一个宏使其更漂亮。

我以前从未见过这种元数据方法,它让我想吐。我看不出这有什么好处;这只是一个粗俗的方式来做一个:私人功能。如果你想要比以下更私密的东西:私密,使用letfn;元数据不是一个合理的折衷方案。@amalloy OP不希望它像
letfn
那样私有。OP希望能够从任何范围访问该函数。因此,将该函数公开,并在其上注明“除非有充分理由,否则不要使用此函数”。或者将其私有化,并通过var进入。嘿,它可能并不漂亮,但它确实看起来是一个有效的解决方案。另外,如前所述,丑陋可以(相当容易)放在宏后面。为什么要对函数的内部逻辑进行单元测试?如果它是如此复杂,以至于需要单独测试各个部分,那么将这些定义放在它们自己的顶级表单中是有好处的。除了可见性,还有一个问题,letfn可能会关闭一个符号,“缠绕”它。Common Lisp的条件系统是否能解决这个问题?如果是这样的话,有没有Clojure的等价物?我认为您需要更多地改变您的思维方式,以编写好的Clojure代码(以及Scheme)。让你的助手函数更具功能性(比如在函数编程中),这样它们就可以安全地在外部公开。我不明白为什么本地函数比顶级函数“功能性差”(或者更不安全)。唯一的区别是可见性——它应该是同一个函数。我仍然认为,使用本地函数会使它们的预期用途对代码读取器更加明显,但很难测试。