Clojure 插入符号作为符号?

发布于 2024-12-27 16:15:59 字数 289 浏览 3 评论 0原文

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

(另外,到底有可能命名一个函数 ^ 吗?)

So I thought it would be a nice idea to name a function that calculates the exponential ^, but it seems like the caret actually does something special, as the Clojure REPL generates an error when evaluating '^. Googling mostly gave me this, so I was wondering what the actualy use for the caret in Clojure is.

(Also, would it be possible after all to name a function ^?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心的憧憬 2025-01-03 16:15:59

^ 是“元字符”,它告诉阅读器添加以 < 开头的符号code>^ 作为下一个符号的元数据(前提是它是实现 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])}

这经常用于类型提示

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

打开反射警告通常是个好主意 (设置! *warn-on-reflection* true) 然后添加类型提示,直到警告消失。如果没有这些,Clojure 将在运行时查找函数操作数的类型,这会省去您为类型而烦恼的麻烦,但代价很小。

PS:我下一个最喜欢的读者字符是“dispatch”字符#,接下来它非常值得学习:)

PPS:这在 clojure 1.2.x 与 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}

^ is "the meta character" it tells the reader to add the symbol starting with ^ as metadata to the next symbol (provided it is something that implements IMetas)

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

You can learn a lot about how clojure works under the hood by looking at the meta of things, for instance functions:

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

this is very often used for type hints

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

it is generally a good idea to turn on reflection warnings (set! *warn-on-reflection* true) and then add type hints until the warnings go away. without these Clojure will look up the type of the function operands at run-time, which saves you the trouble of fussing with types though at a slight cost.

PS: My next favorite reader character is the "dispatch" character #, it is well worth learning about it next :)

PPS: this is different in clojure 1.2.x vs clojure 1.3.x
in Clojure 1.2.1 metadata does not compose when you use the meta-character:

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

and in 1.3 it "does the right thing" and also keywords are options instead of "tags":

user=> (def foo ^:foo ^:bar [1 2 3])
#'user/foo
user=> (meta foo)
{:foo true, :bar true}
雄赳赳气昂昂 2025-01-03 16:15:59

不幸的是,在我看来,你的问题的答案是否定的。在 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)

The same code works with a Regular text name:

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

I will be happy if people with better Clojure-fu比我的可以证明我错了! :)

It seems to me that the answer to your question is, unfortunately, no. In Clojure, you cannot name a function ^.

I tried the following in the REPL:

user=> (println \^)
^
nil

This seems to imply that you can escape the carat (^) with a backslash. However, if I try to declare a function using \^ as a name then I get an error message:

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)

The same code works with a regular text name:

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

I would be delighted if someone with better Clojure-fu than mine could prove me wrong! :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文