Macros lisp defclass宏问题

Macros lisp defclass宏问题,macros,lisp,common-lisp,Macros,Lisp,Common Lisp,有点背景,我是一个完全的口齿不清的人,几周前才开始,但我已经在其他语言中发展了很多年。逻辑没问题,lisp,有问题 我正在尝试编写一个宏,它将为我定义两个clsql类,以解决库中的一个问题。我希望将类命名为x和'x-insert``,因此在宏中我希望宏计算x-insert的符号名,但我很难做到这一点。我的尝试在下面,但我在两件事上被难住了 如何让它创建类名。如果我删除,class-insert中的空格,它将不会求值,这是我理解的,因此我认为我缺少一些直接的方法来告诉它忽略空格,并将名称创建为单个

有点背景,我是一个完全的口齿不清的人,几周前才开始,但我已经在其他语言中发展了很多年。逻辑没问题,lisp,有问题

我正在尝试编写一个宏,它将为我定义两个clsql类,以解决库中的一个问题。我希望将类命名为
x
和'x-insert``,因此在宏中我希望宏计算x-insert的符号名,但我很难做到这一点。我的尝试在下面,但我在两件事上被难住了

如何让它创建类名。如果我删除
,class-insert
中的空格,它将不会求值,这是我理解的,因此我认为我缺少一些直接的方法来告诉它忽略空格,并将名称创建为单个单词,第二个问题是让它创建两个类,而不是一个类,因为它只是从我所看到的使用“宏展开”展开宏的最后一部分

也许我完全走错了方向,所以请随意将我踢向正确的方向

(defmacro gen-pair (class base-slots pkey-slot base-table)
  `(clsql:def-view-class ,class -insert()
     (
      ,base-slots
     )
     (:base-table ,base-table)
   )

  `(clsql:def-view-class ,class (,class -insert)
     (
      ,pkey-slot
     )
     (:base-table ,base-table)
   )
)

很难在这里开始解释,因为你似乎有 一大堆误解

第一个问题(如何编写符号名):Lisp宏不需要 对文本进行操作,但对代码进行操作。以反报价形式,
,类
计算传递到宏的
参数的代码, 在本例中,很可能是一个类名。之后再写一个符号 不会神奇地合并符号名称;为什么要这样做?如果你 要合成新的符号名称,必须构造它:

,(intern (string-upcase (concatenate 'string
                                     (symbol-name class)
                                     "-insert")))
第二个问题(为什么它似乎只扩展了第二部分):问题
defmacro
表单的内容在隐式
progn
(这就是为什么它不抱怨无效数量的参数 这里)。最后一个表单的返回值是 整个
defmacro
表单。在这种情况下,返回值是代码 由反报价表生成。宏定义了一个函数,该函数 将一种形式扩展为一种新形式;不能将其展开为两个 不相关的表格。您必须生成一个包含 你想要两种形式

第三个问题(为什么您的代码与Lispers的代码看起来如此不同
(写下):不要像剪指甲一样乱抛括号。那里 有几个Lisp风格的向导在网上四处飞行。读它们。 我们将从贝赫施特(beherrscht)死亡,但这是斯皮伦(大概是:当你 知道正确的方法,你可以玩它)

第四个问题(如何克服认知的局限性) 你可以直接问这个问题,不是吗?你有什么限制
你的意思是?

这里很难开始解释,因为你似乎有一个 一大堆误解

第一个问题(如何编写符号名):Lisp宏不需要 对文本进行操作,但对代码进行操作。以反报价形式,
,类
计算传递到宏的
参数的代码, 在本例中,很可能是一个类名。之后再写一个符号 不会神奇地合并符号名称;为什么要这样做?如果你 要合成新的符号名称,必须构造它:

,(intern (string-upcase (concatenate 'string
                                     (symbol-name class)
                                     "-insert")))
第二个问题(为什么它似乎只扩展了第二部分):问题
defmacro
表单的内容在隐式
progn
(这就是为什么它不抱怨无效数量的参数 这里)。最后一个表单的返回值是 整个
defmacro
表单。在这种情况下,返回值是代码 由反报价表生成。宏定义了一个函数,该函数 将一种形式扩展为一种新形式;不能将其展开为两个 不相关的表格。您必须生成一个包含 你想要两种形式

第三个问题(为什么您的代码与Lispers的代码看起来如此不同
(写下):不要像剪指甲一样乱抛括号。那里 有几个Lisp风格的向导在网上四处飞行。读它们。 我们将从贝赫施特(beherrscht)死亡,但这是斯皮伦(大概是:当你 知道正确的方法,你可以玩它)

第四个问题(如何克服认知的局限性) 你可以直接问这个问题,不是吗?你有什么限制
你的意思是?

“不要像剪指甲一样乱丢括号”——如果他不知道你的意思,这句话不会帮助他理解任何东西。见鬼,我已经使用Lisp超过15年了(英语比这要长一点),我想我不明白你的意思。(人们倾向于把指甲剪得远远的吗?@svante:我想说的是,虽然STRING-UPCASE在您的情况下是必要的,但是(intern(concatenate'STRING(symbol-name-class)(symbol-name'-insert)))不是更好的解决方案吗,因为它甚至可以在使用不同读取表的常见lisp环境中工作(比如说,不破坏大小写)?另一个给您带来更多灵活性的选项是从字符串读取。这允许您执行以下操作:(从字符串读取(格式为nil“~a-insert”(符号名称类))@Vatine:我刚才给出了遵循默认约定的示例代码。您的解决方案的缺点是符号
'-insert
也将被插入。我喜欢Andrew Myers从字符串
表单读取
。我真正的问题是clsql和在ODBC数据源上插入的问题,以及获取auto inc标识字段af我有一个朋友(真正的lisp家伙)研究了这个问题,他说这是CLSQL的问题,也是一个限制,(适用于mysql,不适用于ODBC)他建议使用类似的方法,这确实有效,但每次定义一个类时都需要我编写两个类。如果可以避免的话,我不想手工编写它们,因为它们只是略有不同,我希望可以使用宏来拯救我。“不要像剪指甲一样乱丢括号”如果他不知道你的意思