当我在 Clojure 中编写这样的函数调用 (my-function [abc]) 时。Clojure 如何找到我的函数?它是否从全局/每个命名空间符号表中执行查找?
我假设符号表被实现为一个哈希表,它为查找提供 O(1) 时间复杂度。它还需要将函数名称作为字符串与表中的符号进行比较,这应该花费 O(n) 时间(n 是符号的长度)。这意味着符号越长,名称解析就越慢。这是对的吗?
当我在 Clojure 中编写这样的函数调用 (my-function [abc]) 时。Clojure 如何找到我的函数?它是否从全局/每个命名空间符号表中执行查找?
我假设符号表被实现为一个哈希表,它为查找提供 O(1) 时间复杂度。它还需要将函数名称作为字符串与表中的符号进行比较,这应该花费 O(n) 时间(n 是符号的长度)。这意味着符号越长,名称解析就越慢。这是对的吗?
Clojure is a compiled language - it compiles directly to JVM bytecode, yet remains completely dynamic.
-From the front page of http://clojure.org/
Compiling means that the Symbols are already prehashed therefor your second statement regarding function name length is only true at compile-time. Also if you are concerned about every CPU cycle a JVM/CLR language will not be your friend for various reasons.
符号使用内部字符串,因此它们与 比较==
,而不是与.equals
。所以即使你说的部分是O(n)也是O(1)。然而,这并不重要,因为所有这些查找 (a) 无论如何都非常快,并且 (b) 发生在编译时,而不是运行时。运行程序后,所有函数调用都已解析为指针取消引用或其类似物。
namespaces indeed behave as maps and you can look at them directly with the ns-map
function:
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>>])
more specifically they map vars to objects.
if you really do want a function to be looked up in it's var so changes propagate through your program instantly you can call the var instead of the function that was contained in the var at compile time, which results in a lookup on every call:
(#'foo 4) looks the function up in the var every time
(foo 4) looks it up in the map once when it's compiled.