首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Clojure deftype作为参数化函数

使用Clojure deftype作为参数化函数
EN

Stack Overflow用户
提问于 2010-07-26 03:22:02
回答 1查看 493关注 0票数 7

我正试图在编译器中使用clojure,因此需要参数化对deftype的调用;然而,我很难将类型提示传递下去。考虑以下代码:

代码语言:javascript
复制
(defn describe [x] 
  (let [fields (.getDeclaredFields x)
        names (map #(.getName %) fields)
        types (map #(.getType %) fields)]
    (interleave types names)))

(defn direct [] (deftype direct-type [^int x]))
(defn indirect-helper [] (list ^int (symbol "x")))
(defn indirect [] (eval `(deftype ~(symbol  "indirect-type") ~(indirect-helper))))

以及来自REPL的以下会话:

代码语言:javascript
复制
Clojure 1.2.0-master-SNAPSHOT
1:1 user=> #<Namespace dataclass>
1:2 dataclass=> (direct)
dataclass.direct-type
1:3 dataclass=> (indirect)
dataclass.indirect-type
1:4 dataclass=> (describe direct-type)
(int "x")
1:5 dataclass=> (describe indirect-type)
(java.lang.Object "x")

注意,为indirect-type生成的类丢失了direct-type所具有的^int提示。我怎样才能得到这些提示呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-07-26 07:32:32

您需要将indirect-helper更改为read

代码语言:javascript
复制
(defn indirect-helper [] [(with-meta (symbol "x") {:tag 'int})])

原因是^int解析为^,然后解析为int;在Clojure1.2中,^引入了读者元数据(在1.1中,您将使用#^,它仍然有效,但在1.2中已弃用)。因此,direct中的^int x被读入为一个clojure.lang.Symbol,它的名称是"x",其元数据映射是{:tag int} (这里的int本身是一个符号)。(在本例中,符号的最后一个组件--它的名称空间--是nil。)

在来自问题文本的indirect-helper版本中,^int被附加到(symbol "x") --由符号symbol和字符串"x"组成的列表(特别意味着(list ^int (symbol "x"))的计算结果是一个包含1个元素的列表)。一旦评估了(symbol "x"),这个“类型提示”就会丢失。要解决这些问题,需要某种方法将元数据附加到由(symbol "x")生成的实际符号。

现在,在这种情况下,符号是在运行时生成的,所以您不能使用读取器元数据将类型提示附加到它。进入with-meta,它在运行时附加元数据(出于与此处相同的原因,在编写宏时经常使用它),这样就节省了时间:

代码语言:javascript
复制
user> (indirect)
user.indirect-type
user> (describe indirect-type)
(int "x")

(顺便说一句,我以为deftype需要一个字段名称的向量,但显然列表也可以……向量当然更符合习惯。)

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3330666

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档