Tag元数据在Clojure中是什么意思?

3

以下示例取自《Clojure编程》第二版

(defn ^{:tag String} shout [^{:tag String} s] (.toUpperCase s))

什么是:tag元数据的价值? 执行以下操作:
((map #'shout) :tag)

产生的结果是 java.lang.String,但如果我不能区分输入和输出参数,那么到底传达了什么信息呢?

3个回答

1

我在阅读第三版《Clojure编程》时遇到了同样的问题,该书有稍微更新的示例:

(defn ^{:tag String} shout [^{:tag String} s] (clojure.string/upper-case s))

这相当于短表单:

; I guess tags and type hints are equivalent
(defn ^String shout [^String s] (clojure.string/upper-case s))

像你所说的,如果查找函数元数据,标签是指输入参数还是输出参数并不明确:

(meta #'shout)

... returns

{:tag java.lang.String,
 :arglists ([s]),
 etc... }

如果你仔细思考,就会明白返回类型是必须的,因为一个函数可以有N个参数,但Clojure不允许多个返回值。元数据中的:tag不是一个向量,而是一个单一的值。
如果你实际上需要以编程方式获取函数参数的标签/类型提示,你可以在:arglists上调用meta函数,如下所示:

https://dev59.com/4oPba4cB1Zd3GeqPx9iH#26116353


0
书籍《Programming Clojure》中的示例不够明确,因为函数返回值和参数类型相同。一个更加明确的示例如下:
(defn ^String strneg [^Double n] (str (- n)))
(meta #'strneg)
; => {:tag java.lang.String, :arglists ([n]), ... ... }

与之比较:

(meta (first (first (:arglists (meta #'strneg)))))
; => {:tag Double}

因此,当您在函数上使用元标记时,标签是该函数返回值的类型提示


0
“:tag”元数据的值是什么?
我找到了一份Clojure官方文档。 Clojure - 元数据
^String obj - Sets the value of :tag key in the object’s metadata.
Equivalent to ^{:tag java.lang.String} obj
Used to hint an objects type to the Clojure compiler. 
See Java Interop: 
  Type Hints for more information and a complete list of special type hints.

类型提示

Clojure supports the use of type hints to assist the compiler 
in avoiding reflection in performance-critical areas of code.

如果我无法区分输入和输出参数,那么到底传达了什么信息?
您不需要为输入或输出参数指定类型。如果未指定,Clojure将使用反射执行函数(根据此描述)。
还有另一个博客文章。根据这篇文章,Clojure对由Clojure代码创建的所有方法都使用IFn接口。
IFn defines all arguments of .invoke to be of type Object.
So you can pass anything you like to a Clojure function.
It doesn't matter which type it is, because everything is an Object anyway. 

所以,我认为在不使用类型提示的情况下调用Clojure方法和调用Java的反射.invoke是相同的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接