【问题标题】:Get the macro to be executed in LISP获取要在 LISP 中执行的宏
【发布时间】:2015-01-27 20:45:46
【问题描述】:

一开始,我创建了一个基于宏的类和访问器,如下所示(这段代码很大程度上来自 Peter Seibel http://www.gigamonkeys.com/book/ 的书)

(defun slot->defclass-slot (spec)
  `(,spec :initarg ,(as-keyword spec) :accessor ,spec :initform 0))
(defmacro define-class (class-name class-slot)
  `(defclass ,class-name ()
       ,(mapcar #'slot->defclass-slot class-slot)))

当我使用宏生成类时,我没有固定的插槽。槽位可以是“name”和“id”,也可以是“name”、“id”和“description”。

之后,我用宏生成了一个类定义,我想创建该类的几个实例。再一次,我尝试构建一个尽可能通用的函数,因为类中的槽数是可变的。

例如,如果我创建一个具有两个插槽“name”和“id”的类。我可能有兴趣使用这个命令:

(defun myfunction (slots)    
`(make-instance 'myclass :name ,(first slots) :id ,(second slots)))

但是,如果我的班级有三个插槽“name”、“id”和“description”,我可能有兴趣使用这个命令:

(defun myfunction (slots)    
    `(make-instance 'myclass :name ,(first slots) :id ,(second slots) :description (third slots)))

不知何故,我成功地定义了一个函数,该函数使用命令 make-instance 和正确的插槽数创建一个列表。这是我如何进行的。 首先,我在宏定义中添加一个属性“slots”到包含插槽列表的类中。

(defmacro define-class (class-name class-slot id-slot)
  `(progn
     (eval-when (:compile-toplevel :load-toplevel :execute)
         (setf (get ',class-name 'slots) ',class-slot))
   (defclass ,class-name ()
      ,(mapcar #'slot->defclass-slot class-slot))

然后我可以生成带有以下文本的命令:

(defun make (slot-title slot-value)
  `(,(as-keyword slot-title) ,slot-value))
(defun list->db (slots-instance)
  `(make-instance 'model 
     ,@(mapcan #'make (get 'model 'slots) slots-instance)))) 
(defmacro make-model (myslots)
   (list->db myslots))

当我执行 list->db 以下输入(“a”“b”)时,我得到以下结果,例如:

(make-instance 'myclass :name "a" :id "b")

但是现在,我想知道如何创建一个函数来获取列表列表(例如 (("k" "u") ("t" "j"))),并针对列表中的每个元素执行命令并创建一个类?

【问题讨论】:

  • 你能解释一下标题与问题有什么关系吗?宏在哪里?为什么要返回列表?当您的代码不这样做时,您为什么要创建一个类?
  • 我建议先澄清你的问题。您可以举一个示例输入和输出示例。不要被反对票鼓励。我有一种感觉,你只是这么新,你不知道如何清楚地表达你的问题。所以,最好按照我上面的建议去做。
  • 我推荐这本书,我应该提到它。现在完成了。

标签: lisp common-lisp


【解决方案1】:

当您使用反引号时,您是在创建一个列表,而不是将其作为表达式执行。它通常用于创建宏。宏将代码转换为其他代码。代码在 Lisp 中表示为列表。

你写的相当于:

(defun myfunction (slots)
  (list 'make-instance ''myclass :name (first slots) :id (second slots)))

你似乎打算这样做:

(defun myfunction (slots)
  (make-instance 'myclass :name (first slots) :id (second slots)))

这个错误似乎源于对你在别处看到的东西的死记硬背,根本不理解。不要那样做。你可能会从阅读一本好书中受益匪浅,例如。 G。 Practical Common Lisp.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多