Macros 我的lisp宏在最新guile中停止工作
我在2010年写了一个宏,它是用来管理结构的,比如使用Alists管理Common Lips(这里是包含函数的整个文件)Macros 我的lisp宏在最新guile中停止工作,macros,scheme,lisp,guile,lisp-macros,Macros,Scheme,Lisp,Guile,Lisp Macros,我在2010年写了一个宏,它是用来管理结构的,比如使用Alists管理Common Lips(这里是包含函数的整个文件) (定义宏(defstruct name.fields) “基于assoc列表在guile中实现宏结构。” (let((名称(映射(lambda(符号)(gensym))字段)) (结构(gensym)) (字段arg(gensym))) `(如果(不是(每个唯一字段)) (错误“defstruct”字段必须唯一) (开始 (定义(,(生成名称),@names) (映射cons
(定义宏(defstruct name.fields)
“基于assoc列表在guile中实现宏结构。”
(let((名称(映射(lambda(符号)(gensym))字段))
(结构(gensym))
(字段arg(gensym)))
`(如果(不是(每个唯一字段))
(错误“defstruct”字段必须唯一)
(开始
(定义(,(生成名称),@names)
(映射cons',字段(列表,@names)))
,@(图(λ(场)
`(定义(,(生成getter名称字段),结构)
(cdr(assq',field,struct)))字段)
,@(图(λ(场)
`(定义(,(生成setter name字段),结构,字段arg)
(assq集合,结构,字段,字段参数)
,字段arg)字段)
(定义(,(生成谓词名称),结构)
(和(struct?,struct)
(let((结果#t))
(每个(λx y)
(如果(不是(等式x y))(设置!结果#f)))
“,字段
(地图车,结构)
结果(()()()))
它工作得很好。我最近为我的(基于scheme)更新了这个宏,当我调用它时,它返回了false
,我想知道这是否是guile中的工作方式。但事实证明这根本不起作用。它显示了这个错误:
编译表达式时:错误:语法错误:未知位置:
表达式上下文中的定义,其中不允许定义,
在形式上(定义(制造点#{g746}##{g747}#)(地图图标(引用x
y) )(列表{g746}{g747})
为什么我会出现这个错误,以及如何修复它,这样它又能在guile中工作?我很久以前就不记得我是如何测试这段代码的了,但使用load函数打开guile或将代码复制粘贴到解释器中都会产生相同的错误
我在GNU/Linux上使用Guile2.0.14
PS:我更喜欢使用lisp宏,因为它们比奇怪的scheme宏更好。现代guile scheme似乎不认为if中的begin是启动新定义上下文的有效选项。这可能是一个bug,或者scheme规范的更好对齐方式。但下面的示例代码显示了修复您的错误的技术最近guile的代码(您可能需要创建define value,因为它是guile.P.S.的最新添加。在guile中使用lisps宏是一个难题,如果您计划进行大量规划,它会给您带来麻烦,宏就像parens,如果您习惯了它会觉得很自然 这是密码
(define-macro (defstruct name . fields)
"Macro implementing structures in guile based on assoc list."
(let* ((names (map (lambda (symbol) (gensym)) fields))
(struct (gensym))
(field-arg (gensym))
(sname (make-name name))
(predname (make-predicate name))
(getnames (map (lambda (f) (make-getter name f)) fields))
(setnames (map (lambda (f) (make-setter name f)) fields)))
`(define-values (,sname ,predname ,@getnames ,@setnames)
(if (not (every-unique ',fields))
(error 'defstruct "Fields must be unique")
(let ()
(define (,sname ,@names)
(map cons ',fields (list ,@names)))
,@(map (lambda (field)
`(define (,(make-getter name field) ,struct)
(cdr (assq ',field ,struct)))) fields)
,@(map (lambda (field)
`(define (,(make-setter name field) ,struct ,field-arg)
(assq-set! ,struct ',field ,field-arg)
,field-arg)) fields)
(define (,predname ,struct)
(and (struct? ,struct)
(let ((result #t))
(for-each (lambda (x y)
(if (not (eq? x y)) (set! result #f)))
',fields
(map car ,struct))
result)))
(values ,sname ,predname ,@getnames ,@setnames))))))
这是一个版本的定义值
(查看#'
后面的代码,了解它的作用)
我认为
if
可能是在编译时完成的(在宏中,而不是结果),因为字段是给定的。因此结果可能是(begin…)
而没有if
(define-syntax define-values
(lambda (x)
(syntax-case x ()
((_ (f ...) code ...)
(with-syntax (((ff ...) (generate-temporaries #'(f ...))))
#'(begin
(define f #f)
...
(call-with-values (lambda () code ...)
(lambda (ff ...)
(set! f ff)
...))))))))