Macros lisp宏中的符号操作

Macros lisp宏中的符号操作,macros,common-lisp,symbols,Macros,Common Lisp,Symbols,我正在为Lisp语言编写一个玩具解释器,其中我有以下CL代码: (异常列表(&rest参数) (make-mal:类型“列表 :值(args)) (注册乐趣列表) (异常列表?(arg) (均衡器(mal类型参数)列表) (注册乐趣列表?|#错误列表?) 然而,我更愿意这样写: (defmacro defmal (name lambda-list &body body) (let ((mal-name (intern (concatenate 'string "MAL-" (sym

我正在为Lisp语言编写一个玩具解释器,其中我有以下CL代码:

(异常列表(&rest参数)
(make-mal:类型“列表
:值(args))
(注册乐趣列表)
(异常列表?(arg)
(均衡器(mal类型参数)列表)
(注册乐趣列表?|#错误列表?)
然而,我更愿意这样写:

(defmacro defmal (name lambda-list &body body)
  (let ((mal-name (intern (concatenate 'string "MAL-" (symbol-name name))))
        (mal-norm (intern (string-downcase name))))
    `(progn
       (defun ,mal-name ,lambda-list
          ,@body)
       (register-function ',mal-norm #',mal-name))))
(定义列表(&rest参数)
(make-mal:类型“列表
:值(args))
(除故障列表?(arg)
(均衡器(mal类型参数)列表)
我试着写一个宏来实现这一点,但我在条形图的符号方面遇到了问题(我很困惑这是什么!)。这就是我所尝试的:

(defmacro defmal(名称参数和正文)
(let((funsym(intern)(格式nil”~{~a~}`(mal-,name())))
`(注册fun` |,name |(defun,funsym,args,@body)))
这不起作用,因为
,“name”
字面意思是
,“name”
,而不是
,“list”


我猜这是一个XY问题,但我不知道如何解决这个问题。

语法只是Lisp打印机打印名称中有需要转义字符的符号的方法之一(并且读取器可以读取名称中有这些字符的符号):

还有其他方法,包括转义单个字符:

(print '|FOO|)
;=> FOO

(print '\f\o\o)
;=> |foo| 
你要做的只是创建一个名称包含小写字母的符号。这很容易,如上所示。不过,您的问题之一是,您将获得一个名称中充满大写字母的符号作为输入,因此您需要首先对其进行简化:

CL-USER> (symbol-name 'FOO)
;=> "FOO"

CL-USER> (intern (symbol-name 'FOO))
;=> FOO

CL-USER> (string-downcase (symbol-name 'FOO))
;=> "foo"

CL-USER> (intern (string-downcase (symbol-name 'FOO)))
;=> |foo|
事实上,由于字符串downcase采用字符串指示符,而不仅仅是字符串,因此可以直接传入符号:

CL-USER> (intern (string-downcase 'BaR))
;=> |bar|
所以,在所有的字符串处理之后,我们可以转到宏


听起来你在找这样的东西:

(defmacro defmal (name lambda-list &body body)
  (let ((mal-name (intern (concatenate 'string "MAL-" (symbol-name name))))
        (mal-norm (intern (string-downcase name))))
    `(progn
       (defun ,mal-name ,lambda-list
          ,@body)
       (register-function ',mal-norm #',mal-name))))


通常最好避免在生成符号名时使用格式,因为具体的输出可能会根据其他变量而改变。例如:

(loop for case in '(:upcase :downcase :capitalize)
   collect (let ((*print-case* case))
             (format nil "~a" 'foo)))
;=> ("FOO" "foo" "Foo")
相反,您可以使用与字符串(或符号的符号名称)连接起来。因为读者也可以有不同的区分大小写设置,有时我甚至会这样做(但不是每个人都喜欢这样):


这样,如果读取器执行任何异常操作(例如,保留大小写,以便
mal-
的符号名为
“mal-
),您也可以将其保存在自己生成的符号中。

语法只是Lisp打印机打印名称中包含需要转义的字符的符号的方法之一(并且读取器可以读取名称中包含此类字符的符号):

还有其他方法,包括转义单个字符:

(print '|FOO|)
;=> FOO

(print '\f\o\o)
;=> |foo| 
您试图做的只是创建一个名称包含小写字母的符号。这很简单,如上所示。但您的部分问题是,您将得到一个名称中充满大写字母的符号作为输入,因此您需要先将其小写:

CL-USER> (symbol-name 'FOO)
;=> "FOO"

CL-USER> (intern (symbol-name 'FOO))
;=> FOO

CL-USER> (string-downcase (symbol-name 'FOO))
;=> "foo"

CL-USER> (intern (string-downcase (symbol-name 'FOO)))
;=> |foo|
事实上,由于字符串downcase采用字符串指示符,而不仅仅是字符串,因此可以直接传入符号:

CL-USER> (intern (string-downcase 'BaR))
;=> |bar|
所以,在所有的字符串处理之后,我们可以转到宏


听起来你在找这样的东西:

(defmacro defmal (name lambda-list &body body)
  (let ((mal-name (intern (concatenate 'string "MAL-" (symbol-name name))))
        (mal-norm (intern (string-downcase name))))
    `(progn
       (defun ,mal-name ,lambda-list
          ,@body)
       (register-function ',mal-norm #',mal-name))))


通常最好避免在生成符号名时使用格式,因为具体的输出可能会根据其他变量而改变。例如:

(loop for case in '(:upcase :downcase :capitalize)
   collect (let ((*print-case* case))
             (format nil "~a" 'foo)))
;=> ("FOO" "foo" "Foo")
相反,您可以使用与字符串(或符号的符号名称)连接起来。因为读取器也可以有不同的区分大小写设置,有时我甚至会这样做(但不是每个人都喜欢):

这种方式,如果读者有任何异常(例如,保存案例,以便代码名> MAL-<代码> <代码> > MAL-<代码> >,您也可以将它保存在您自己生成的符号中。

< P>此外,考虑使用库中的函数:

  • 格式符号
    类似,但在内部。此处,
    t
    代表当前包,名称为downcased:

    (format-symbol t "mal-~(~A~)" name)
    => |mal-list|
    
  • symbolicate
    在当前包中连接和插入:

    (symbolicate '#:mal- name)
    
    如果当前的可读表是否保留大小写,则可以使用
    |MAL-LIST |
    |MAL-LIST |
    。为完整起见,请注意,
    可读大小写
    可以设置为:
    :upcase
    :downcase
    :preserve
    :invert
    (我觉得这一个很有趣)

除此之外,考虑使用库中的函数:

  • 格式符号
    类似,但在内部。此处,
    t
    代表当前包,名称为downcased:

    (format-symbol t "mal-~(~A~)" name)
    => |mal-list|
    
  • symbolicate
    在当前包中连接和插入:

    (symbolicate '#:mal- name)
    
    如果当前的可读表是否保留大小写,则可以使用
    |MAL-LIST |
    |MAL-LIST |
    。为完整起见,请注意,
    可读大小写
    可以设置为:
    :upcase
    :downcase
    :preserve
    :invert
    (我觉得这一个很有趣)


符号有名称。默认情况下,当读卡器遇到(例如,
foo
)时,它将获取字符串
“foo”
,将其升级为获取
“foo”
,并将其升级为获取符号
foo
。但符号不必有大写的名称。如果你实习
“foo”
(与
“foo”
)你会得到一个可能会被打印的符号
\f\o\o
\foo |
(格式nil”~{~a~}是不可预测的,因为
*打印案例*
可以被设置为各种事情。
(格式nil”~a“foo)
可能返回“foo”