3

在以下示例中(取自Programming Clojure,第 2 版一书:

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

:tag元数据的价值是什么?做一个:

((map #'shout) :tag)

产生java.lang.String但如果我无法区分输入和输出参数,究竟传达了什么信息?

4

2 回答 2

1

我在阅读第三版 Programming 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)

...返回

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

如果您考虑一下,它必须是返回类型,因为函数可以有 N 个参数,但 Clojure 不允许多个返回值。元数据中的 :tag 不是向量,而是单个值。

如果您实际上以编程方式需要函数参数的标记/类型提示,您可以调用 :arglists 上的元函数,如下所示:

https://stackoverflow.com/a/26116353/695318

于 2018-02-26T20:16:38.083 回答
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是一样的。

于 2017-03-15T04:11:08.150 回答