获取要在LISP中执行的宏

时间:2015-01-27 20:45:47

标签: lisp common-lisp

一开始,我创建了一个基于宏的类和访问器(这段代码很大程度上来自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”))),以及列表的每个元素执行命令并创建一个类?

1 个答案:

答案 0 :(得分:3)

使用反引号时,您正在创建一个列表,而不是将其作为表达式执行。它通常用于创建宏。宏将代码转换为其他代码。代码在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