如何在Common Lisp的defenum中定义同名枚举成员?
问题:在Common Lisp的defenum中实现跨枚举类的同名成员
定义的枚举代码
Manufacturer枚举
(in-package :useragentutils-cl) ;; name是关键字,故改为namee (defenum:defenum (Manufacturer (:initargs (id namee))) ( (MOZILLA(13 "Mozilla Foundation")) ) ((id) (namee) ) )
RenderingEngine枚举
(in-package :useragentutils-cl) (defenum:defenum (RenderingEngine (:initargs (namee))) ( (MOZILLA("Mozilla")) ) ((namee)) ())
编译错误信息
编译RenderingEngine时触发第一个错误:
Execution of a form compiled with errors. Form: (IT.UNIMIB.DISCO.MA.COMMON-LISP.EXTENSIONS.DATA-AND-CONTROL-FLOW.DEFENUM:DEFENUM (RENDERINGENGINE (:INITARGS (NAMEE))) ((EDGE_HTML 1 ("EdgeHTML")) (TRIDENT 2 ("Trident")) (WORD ("Microsoft Office Word")) (GECKO ("Gecko")) (WEBKIT ("WebKit")) (PRESTO ("Presto")) (MOZILLA ("Mozilla")) (KHTML ("KHTML")) (BLINK ("Blink")) (OTHER ("Other"))) ((NAMEE)) NIL) Compile-time error: (during macroexpansion of (IT.UNIMIB.DISCO.MA.COMMON-LISP.EXTENSIONS.DATA-AND-CONTROL-FLOW.DEFENUM:DEFENUM (RENDERINGENGINE #) ...)) Tag MOZILLA is part of enum MANUFACTURER; it cannot be added to enum RENDERINGENGINE. [Condition of type SB-INT:COMPILED-PROGRAM-ERROR]
尝试修改defenum源码,将(get tag '%%enum%%) e中的e设为nil后,触发第二个错误:
The constant MOZILLA is being redefined (from 13 to 7) [Condition of type SB-EXT:DEFCONSTANT-UNEQL] See also: Common Lisp Hyperspec, DEFCONSTANT [:macro] SBCL Manual, Idiosyncrasies [:node]
问题根源分析
查看defenum源码,发现两处核心限制:
- 枚举标签通过
get函数绑定到%%enum%%属性,每个标签只能归属一个枚举类:
(loop for (tag tag-id) in ',tags-specs do (setf (get tag '%%enum%%) e (gethash tag-id id-map) (tag-of e (the symbol tag))))
- defenum会将枚举标签以
defconstant全局定义,导致同名标签无法重复定义:
;; Building init code. (let ((tags-defconstants (loop for (tag tag-id) in tags-specs unless (keywordp tag) if (numberp tag-id) collect `(defconstant ,tag ,tag-id) else if (and (listp tag-id) (eq 'eql (first tag-id))) collect `(defconstant ,tag ,(second tag-id)))) )
Java中的参考实现
Java支持不同枚举类定义同名成员,示例代码如下:
package com.jq; public enum Manufacturer { MOZILLA(13, "Mozilla Foundation"); private final short id; private final String name; private Manufacturer(int id, String name) { this.id = (byte) id; this.name = name; } public short getId() { return id; } public String getName() { return name; } } public enum RenderingEngine { MOZILLA(13, "Mozilla Foundation"); private final short id; private final String name; private RenderingEngine(int id, String name) { this.id = (byte) id; this.name = name; } public short getId() { return id; } public String getName() { return name; } }
需求
希望在Common Lisp的defenum中实现类似Java的效果,允许不同枚举类中存在同名的枚举成员。
内容的提问来源于stack exchange,提问作者catmore
相关产品推荐
相关产品推荐

