Macros lisp宏中的符号操作
我正在为Lisp语言编写一个玩具解释器,其中我有以下CL代码: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
(异常列表(&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>此外,考虑使用库中的函数:
类似,但在内部。此处,格式符号
代表当前包,名称为downcased:t
(format-symbol t "mal-~(~A~)" name) => |mal-list|
在当前包中连接和插入:symbolicate
如果当前的可读表是否保留大小写,则可以使用(symbolicate '#:mal- name)
或|MAL-LIST |
。为完整起见,请注意,|MAL-LIST |
可以设置为:可读大小写
,:upcase
,:downcase
或:preserve
(我觉得这一个很有趣):invert
除此之外,考虑使用库中的函数:
类似,但在内部。此处,格式符号
代表当前包,名称为downcased:t
(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”