为定义语法的 let 绑定寻找替代方案

问题描述

我正在尝试将一些旧的 guile 1.8 代码更新为 guile 3.x。我正在努力为特定构造找到一个好的替代品。

这是一个代表旧的 1.8 代码的示例:

(define h (make-hash-table 31))

(define (def-node name-args types)
  (let ((name (car name-args))
        (args (cdr name-args)))
    (hashq-set! h name
                (list name args types))))

(define define-node
  (defmacro:Syntax-transformer
    (lambda arg-list
      (apply def-node arg-list)
      #f)))

(define (make-nodes)
  (let ((def define-node))
    (def (a b . c) (BT . CT))
    (def (d e . f) (ET . FT))))

(make-nodes)

(display (hashq-ref h 'a))
(newline)
(display (hashq-ref h 'd))
(newline)

我希望在保持 define-node 不变的情况下更新 def-node 和/或 make-nodes。到目前为止,我已经像这样重写了 define-node

(define-Syntax define-node
  (lambda (x)
    (Syntax-case x ()
      [(_ name-args arg-types)
       #'(def-node 'name-args 'arg-types)])))

这似乎是 define-node 的合理替代品,但它不适用于当前的 make-nodeslet 中的 make-nodes 无效。我必须用这个替换 make-nodes

(define (make-nodes)
    (define-node (a b . c) (BT . CT))
    (define-node (d e . f) (ET . FT)))

哪个没问题,但我想知道是否可以找到不需要修改 make-nodes解决方案?

解决方法

您需要更改 make-nodes。如果你考虑像

这样的表达
(let ((def define-node))
  (def (a b . c) (BT . CT))
  (def (d e . f) (ET . FT))))

什么是一样的

((λ (def)
   (def (a b . c) (BT . CT))
   (def (d e . f) (ET . FT)))
 define-node)

然后对 (def (a b . c) (BT . CT)) 的评估涉及首先评估参数......这将失败。

我不清楚这在正常版本的 let 下如何运作。

所以你需要使用类似 let-syntax 的东西来制作一个本地宏。我不知道 Guile 是否有,但如果没有,应该。


我认为,在 R5RS 方案中,如果您添加 make-hasheqvhash-set!,我实际上使用 Racket 对此进行了测试,但是使用带有 R5RS 模块语言的 #%require适合 (define h (make-hasheqv)) (define (def-node name-args types) (let ((name (car name-args)) (args (cdr name-args))) (hash-set! h name (list name args types)))) (define (make-nodes) (let-syntax ((def (syntax-rules () ((_ name-args types) (def-node 'name-args 'types))))) (def (a b . c) (BT . CT)) (def (d e . f) (ET . FT)))) 获取散列位:

{{1}}