You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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源码,发现两处核心限制:

  1. 枚举标签通过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))))
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 11:53:14