LISP 宏失败,崩溃史莱姆
LISP macro fail, crashes slime
我在 emacs 中使用 common lisp 和 slime 并试图定义一个简单的宏。但是,当我 运行 宏时,emacs 粘液缓冲区变得无响应,我的计算机很快变得无法使用。即使在退出 emacs 后,我也会在 bash 提示符下收到有关无法分配内存的错误消息。
我想用我的宏来写这两个函数
(defun triad (foo scale)
"Generates a triad on scale-step FOO of scale SCALE"
(list (%part (- foo 1) scale)
(%part (+ foo 1) scale)
(%part (+ foo 3) scale)))
(defun quad (foo scale)
"Generates a quad on scale step FOO of scale SCALE"
(list (%part (- foo 1) scale)
(%part (+ foo 1) scale)
(%part (+ foo 3) scale)
(%part (+ foo 5) scale)))
使用类似
的语法
(defchord 'mtriad '(1 3 5))
(defchord 'mquad '(1 3 5 7))
我决定使用 mapcar 和 lambda 函数来生成我想要的输出。在解释器中,这可以生成我想要的:
CL-USER> (mapcar (lambda (x) `(%part (+ ,x 2) scale)) '(1 3 5))
((%PART (+ 1 2) SCALE) (%PART (+ 3 2) SCALE) (%PART (+ 5 2) SCALE))
然而,当我试图将它放入宏中以生成 defun 调用时,它会崩溃并在我调用它时立即破坏我的记忆:
(defmacro defchord (name steps)
`(defun ,name (foo scale)
(quote ,(mapcar (lambda (x) `(%part (+ ,x 2) scale)) steps))))
我希望这是一个简单的菜鸟错误!
这是我生成您最初列出的函数的宏的实现:
(defmacro defchord (name steps)
`(defun ,name (foo scale)
,(concatenate 'string "Generates a " (symbol-name name) " on scale-step FOO of scale SCALE")
(list ,.(mapcar (lambda (i) `(%part (+ foo ,i) scale)) steps))))
一些示例:
> (macroexpand-1 '(defchord triad (-1 1 3)))
(DEFUN TRIAD (FOO SCALE)
"Generates a TRIAD on scale-step FOO of scale SCALE"
(LIST (%PART (+ FOO -1) SCALE) (%PART (+ FOO 1) SCALE)
(%PART (+ FOO 3) SCALE)))
> (macroexpand-1 '(defchord quad (-1 1 3 5)))
(DEFUN QUAD (FOO SCALE)
"Generates a QUAD on scale-step FOO of scale SCALE"
(LIST (%PART (+ FOO -1) SCALE) (%PART (+ FOO 1) SCALE)
(%PART (+ FOO 3) SCALE) (%PART (+ FOO 5) SCALE)))
我认为这看起来非常适合您列出的功能。 :-)
你在引号内引用,并且你在引用你的参数,就好像它们是函数一样。如果这是可以接受的,你可以把它变成一个函数:
(defun defchord (name steps)
(setf (symbol-function name)
(lambda (foo scale)
(mapcar (lambda (step)
(%part (+ foo step) scale))
steps)))
name)
;; test
(defchord 'mtriad '(1 3 5)) ;==> mtriad
(defun %part (x y) (cons x y))
(mtriad 2 10) ; ==> ((3 . 10) (5 . 10) (7 . 10))
我在 emacs 中使用 common lisp 和 slime 并试图定义一个简单的宏。但是,当我 运行 宏时,emacs 粘液缓冲区变得无响应,我的计算机很快变得无法使用。即使在退出 emacs 后,我也会在 bash 提示符下收到有关无法分配内存的错误消息。
我想用我的宏来写这两个函数
(defun triad (foo scale)
"Generates a triad on scale-step FOO of scale SCALE"
(list (%part (- foo 1) scale)
(%part (+ foo 1) scale)
(%part (+ foo 3) scale)))
(defun quad (foo scale)
"Generates a quad on scale step FOO of scale SCALE"
(list (%part (- foo 1) scale)
(%part (+ foo 1) scale)
(%part (+ foo 3) scale)
(%part (+ foo 5) scale)))
使用类似
的语法(defchord 'mtriad '(1 3 5))
(defchord 'mquad '(1 3 5 7))
我决定使用 mapcar 和 lambda 函数来生成我想要的输出。在解释器中,这可以生成我想要的:
CL-USER> (mapcar (lambda (x) `(%part (+ ,x 2) scale)) '(1 3 5))
((%PART (+ 1 2) SCALE) (%PART (+ 3 2) SCALE) (%PART (+ 5 2) SCALE))
然而,当我试图将它放入宏中以生成 defun 调用时,它会崩溃并在我调用它时立即破坏我的记忆:
(defmacro defchord (name steps)
`(defun ,name (foo scale)
(quote ,(mapcar (lambda (x) `(%part (+ ,x 2) scale)) steps))))
我希望这是一个简单的菜鸟错误!
这是我生成您最初列出的函数的宏的实现:
(defmacro defchord (name steps)
`(defun ,name (foo scale)
,(concatenate 'string "Generates a " (symbol-name name) " on scale-step FOO of scale SCALE")
(list ,.(mapcar (lambda (i) `(%part (+ foo ,i) scale)) steps))))
一些示例:
> (macroexpand-1 '(defchord triad (-1 1 3)))
(DEFUN TRIAD (FOO SCALE)
"Generates a TRIAD on scale-step FOO of scale SCALE"
(LIST (%PART (+ FOO -1) SCALE) (%PART (+ FOO 1) SCALE)
(%PART (+ FOO 3) SCALE)))
> (macroexpand-1 '(defchord quad (-1 1 3 5)))
(DEFUN QUAD (FOO SCALE)
"Generates a QUAD on scale-step FOO of scale SCALE"
(LIST (%PART (+ FOO -1) SCALE) (%PART (+ FOO 1) SCALE)
(%PART (+ FOO 3) SCALE) (%PART (+ FOO 5) SCALE)))
我认为这看起来非常适合您列出的功能。 :-)
你在引号内引用,并且你在引用你的参数,就好像它们是函数一样。如果这是可以接受的,你可以把它变成一个函数:
(defun defchord (name steps)
(setf (symbol-function name)
(lambda (foo scale)
(mapcar (lambda (step)
(%part (+ foo step) scale))
steps)))
name)
;; test
(defchord 'mtriad '(1 3 5)) ;==> mtriad
(defun %part (x y) (cons x y))
(mtriad 2 10) ; ==> ((3 . 10) (5 . 10) (7 . 10))