macros - 我的 lisp 宏在最新版本中停止工作

标签 macros scheme lisp guile lisp-macros

我在 2010 年编写了宏,它用于使用 Alists 管理 Common Lips 中的结构(这里是包括函数 https://jcubic.pl/struct.txt 的整个文件)。

(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)))
    `(if (not (every-unique ',fields))
        (error 'defstruct "Fields must be unique")
        (begin
          (define (,(make-name name) ,@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 (,(make-predicate name) ,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)))))))

一切正常。我最近为我的 LIPS in JavaScript 更新了这个宏(它基于方案),当我调用它时,它返回 false 并想知道这是否是它的工作原理。但事实证明,这种欺骗根本行不通。它显示此错误:

While compiling expression: ERROR: Syntax error: unknown location: definition in expression context, where definitions are not allowed, in form (define (make-point #{ g746}# #{ g747}#) (map cons (quote (x y)) (list #{ g746}# #{ g747}#))

为什么我会遇到这个错误以及如何修复它,以便它再次正常工作?我很久以前不记得我是如何测试这段代码的,但是使用加载函数打开 guile 或将代码复制粘贴到解释器中都会给出相同的错误。

我在 GNU/Linux 上使用 guile 2.0.14。

PS:在我看来,我更喜欢使用 lisp 宏,它们优于奇怪的方案卫生宏。

最佳答案

看起来现代的欺骗方案没有将 if 中的开始视为启动新定义上下文的有效选项。这可能是一个错误,或者是方案规范的更好调整。但是下面的示例代码展示了修复代码以获取更新的 guile 的技术(您可能需要创建定义值,因为它是 guile 的最新添加内容。P.S. 在 guile 中使用 lisps 宏是一种困惑,它会让您陷入困境如果你打算计划很多就麻烦了,宏就像括号一样,如果你习惯了就会觉得很自然。

这是代码,

(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))))))

这是 define-values 的一个版本(查看 #' 之后的代码,看看它的作用)

(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)
                     ...))))))))

关于macros - 我的 lisp 宏在最新版本中停止工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55686118/

相关文章:

c - MIPS 和英特尔 C 编译器之间的宏定义是否兼容?

c - #定义 PARTS_COLUMN "| %-16s | %-50s |\n"

emacs - Emacs 中的方案编辑 - 模式和键盘布局

Lisp:读取包含 url 的文件

c - 像宏这样的功能是什么意思?

c - 计算访问位域的哪个元素的宏

emacs 方案 Racket 自动重新加载文件

recursion - 方案反转列表

loops - elisp: do 子句语法错误

lisp - 任何人都可以帮助编写一个 lisp 代码来找到满足列表中谓词的第一个元素