Clojure插入符号作为符号?

时间:2012-01-19 01:55:32

标签: clojure caret

所以我认为命名一个计算指数^的函数是一个不错的主意,但看起来插入符实际上做了一些特殊的事情,因为Clojure REPL在评估{{1}时会产生错误}。谷歌搜索主要给了我this,所以我想知道Clojure中插入符号的实际用途是什么。

(另外,是否可以命名一个函数'^?)

2 个答案:

答案 0 :(得分:40)

^是“元字符”,它告诉the reader将以^开头的符号作为元数据添加到下一个符号(假设它是实现IMetas的东西)

user=> (def x ^:IamMeta [1 2 3])
#'user/x
user=> x
[1 2 3]
user=> (meta x)
{:tag :IamMeta}
user=> 

通过查看事物的meta,您可以了解很多关于clojure如何工作的知识,例如函数:

user=> (meta foo)                          
{:ns #<Namespace user>, 
 :name foo, :file "NO_SOURCE_PATH", 
 :line 5, :arglists ([s])}

这经常用于type hints

(defn foo [^String s] (.charAt s 1))

通常最好打开反射警告(set! *warn-on-reflection* true),然后添加类型提示,直到警告消失为止。如果没有这些Clojure,它会在运行时查找函数操作数的类型,这样可以节省大量类型的烦恼。

PS:我的下一个最喜欢的读者角色是“发送”角色#,下一步值得学习:)

PPS:这在clojure 1.2.x vs clojure 1.3.x中有所不同 在Clojure 1.2.1中,当您使用元字符时,元数据不会组成:

user=> (def foo ^:foo ^:bar [1 2 3])
#'user/foo
user=> (meta foo)
{:tag :foo}

并且在1.3中它“做正确的事”并且关键字也是选项而不是“标签”:

user=> (def foo ^:foo ^:bar [1 2 3])
#'user/foo
user=> (meta foo)
{:foo true, :bar true}

答案 1 :(得分:0)

在我看来,不幸的是,你的问题的答案是否定的。在Clojure中,您不能将函数命名为^

我在REPL中尝试了以下内容:

user=> (println \^)
^
nil

这似乎暗示你可以用反斜杠逃脱克拉(^)。但是,如果我尝试使用\^作为名称声明一个函数,那么我会收到一条错误消息:

user=> (defn \^ [n e] (cond (= e 0) 1 :else (* n (\^ n (- e 1)))))
IllegalArgumentException First argument to defn must be a symbol
clojure.core/defn (core.clj:277)

相同的代码使用常规文本名称:

user=> (defn exp [n e] (cond (= e 0) 1 :else (* n (exp n (- e 1)))))
#'user/exp
user=> (exp 3 3)
27

如果有一个比我更好的Clojure-fu的人可以证明我错了,我会很高兴的! :)