【发布时间】:2012-10-26 17:34:02
【问题描述】:
当我在 Clojure 中编写这样的函数调用 (my-function [a b c]) 时。 Clojure 如何找到我的函数?它是否从全局/每个命名空间符号表中进行查找?
我假设符号表被实现为一个哈希表,它为查找提供 O(1) 时间复杂度。它还需要将函数名称作为字符串与表中的符号进行比较,这应该花费 O(n) 时间(n 是符号的长度)。这意味着符号越长,名称解析就越慢。对吗?
【问题讨论】:
标签: clojure
当我在 Clojure 中编写这样的函数调用 (my-function [a b c]) 时。 Clojure 如何找到我的函数?它是否从全局/每个命名空间符号表中进行查找?
我假设符号表被实现为一个哈希表,它为查找提供 O(1) 时间复杂度。它还需要将函数名称作为字符串与表中的符号进行比较,这应该花费 O(n) 时间(n 是符号的长度)。这意味着符号越长,名称解析就越慢。对吗?
【问题讨论】:
标签: clojure
Clojure 是一种编译语言 - 它直接编译为 JVM 字节码, 但仍保持完全动态。
-来自http://clojure.org/的首页
编译意味着符号已经预先散列,因为您关于函数名称长度的第二条语句仅在编译时为真。此外,如果您担心每个 CPU 周期,由于各种原因,JVM/CLR 语言不会成为您的朋友。
【讨论】:
符号使用内部字符串,因此它们与== 进行比较,而不是与.equals 进行比较。所以即使你说的部分是O(n)也是O(1)。然而,这并不重要,因为所有这些查找 (a) 无论如何都非常快,并且 (b) 发生在编译时,而不是运行时。一旦你运行你的程序,所有的函数调用都被解析为指针解引用或类似的一些。
【讨论】:
命名空间确实像地图一样,您可以直接使用ns-map 函数查看它们:
autotestbed.core> (pprint (take 5 (ns-map *ns*)))
nil
([sorted-map
#<Var@6899a7ce:
#<core$sorted_map clojure.core$sorted_map@5875c014>>]
[read-line
#<Var@1de9e86e: #<core$read_line clojure.core$read_line@57c00972>>]
[re-pattern
#<Var@74064c7b:
#<core$re_pattern clojure.core$re_pattern@37d02427>>]
[keyword?
#<Var@4798088a:
#<core$keyword_QMARK_ clojure.core$keyword_QMARK_@630b813f>>]
[hta-deploy-cmd
#<Var@7a7bce95:
#<core$hta_deploy_cmd autotestbed.core$hta_deploy_cmd@6a6a782d>>])
更具体地说,它们将变量映射到对象。
如果您确实希望在其 var 中查找函数,以便更改立即通过您的程序传播,您可以调用 var 而不是在编译时包含在 var 中的函数,这会导致在每个调用:
(#'foo 4) looks the function up in the var every time
(foo 4) looks it up in the map once when it's compiled.
【讨论】: