我能以某种方式找到所有采用特定类型参数的函数/宏吗?
例如,什么函数接受Namespace对象作为参数?
(这是因为我可以创建命名空间并将其存储在var中,但我不知道在哪里可以使用该var;我可以将该var传递给哪个函数?)
这里有一些代码:
user=> (def working-namespace (create-ns 'my-namespace))
#'user/working-namespace
;i created a namspace and want to use it later
user=> (class working-namespace)
clojure.lang.Namespace
; out of curiosity i found out that "working-namespace" is a Namespace object
user=> (ns working-namespace)
nil
working-namespace=>
; but how do i switch to it ? this didn't do what i wanted...
user=> (refer working-namespace)
java.lang.ClassCastException: clojure.lang.Namespace cannot be cast to clojure.lang.Symbol (NO_SOURCE_FILE:0)
; this did not work either as my expectations
user=> (the-ns working-namespace)
#<Namespace my-namespace>
user=> (class (the-ns working-namespace))
clojure.lang.Namespace
; great, this gave me the same thing, a Namespace
因此问题:我如何动态地使用它(这就是我将命名空间放入var的原因)?如何从指向命名空间的var中获取对我有用的东西?
我可以尝试四处寻找使用Namespace对象或将其转换为其他对象的函数。我做了,只找到了“实习生”。手工搜索似乎没有那么有希望
如果我有一百万次这个问题怎么办?是否有一种自动化的方式来获取我正在寻找的东西,而不必每次都询问?答案 0 :(得分:4)
在Clojure 1.2和之前的函数参数中没有类型。 每个函数参数都是一个对象。所以这个问题真的变成了“我如何找到将对象传递给这种类型的对象的函数。所以搜索类型提示会找到其中的一些,虽然它不会得到你所有的东西。我希望它更有可能回答这个问题总的来说。
从1.3(当前dev分支9/2010)开始,函数参数和返回类型可以具有已定义的类型,并将作为该类型传递/返回,而不是强制转换为对象,然后在另一侧进行转换。这会从数值函数的排出时间中删除一个零,其重要的限制是仅适用于:静态函数并且仅用于直接调用(即:不通过map / reduce / filter / etc. )虽然它有一个重要的突破性变化,但是默认情况下整数不再被包装,并且整数(实际上是Long)溢出会引发异常。你可以阅读更多here
(defn ^:static fib ^long [^long n]
(if (<= n 1)
1
(+ (fib (dec n)) (fib (- n 2)))))
所以在1.3发布并被广泛采用之后,你将会看到具有更常用类型的代码,因为它们将提供很大的速度优势,然后你将能够通过参数类型找到更多函数,但仍然不是全部。
在我学习函数参数类型的同一个讲座中,Rich提到了远程Clojure未来(在Clojure中的Clojure之后)关于更好地支持将编译器内部暴露给IDE等工具的计划。所以有希望有一天你会得到这个问题的真实答案。 动态语言在实践中使这稍微困难,理论上要困难得多。
答案 1 :(得分:2)
你已经得到了Arthur的一个很好的答案,所以我只会回答“我如何从指向名称空间的var中获取对我有用的东西?”。从(doc ns)
开始,请注意未评估:
user=> (doc ns)
-------------------------
clojure.core/ns
([name docstring? attr-map? references*])
Macro
Sets *ns* to the namespace named by name (unevaluated), creating it
现在你可以用in-ns
做一些事情(整个命名空间对象 - &gt;字符串 - &gt;符号转换可能很愚蠢,但足以说明我的观点):
user=> (in-ns (symbol (str working-namespace)))
#<Namespace my-namespace>
my-namespace=>
答案 2 :(得分:0)
如果没有动态语言中的大量hackery,我认为你不能做到这一点。如果你现在想要使用命名空间的函数来查看命名空间内容的文档。
例如清理命名空间或重新加载它们。
答案 3 :(得分:0)
您写道:
user=> (ns working-namespace) nil working-namespace=> ; but how do i switch to it ? this didn't do what i wanted...
但是已经切换到working-namespace
命名空间(这就是提示更改的原因),所以我不清楚“你想要什么”。
正如我前面提到的,你需要提出你试图解决的最终问题。完全有可能弄乱命名空间对象不是解决方案。