找到定义语法的 let 绑定的替代方法
finding an alternative for a let binding of a define-syntax
我正在尝试将一些旧的 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
and/or 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-nodes
,make-nodes
中的 let
无效。我必须用这个替换 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-hasheqv
和 hash-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))))
我正在尝试将一些旧的 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
and/or 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-nodes
,make-nodes
中的 let
无效。我必须用这个替换 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-hasheqv
和 hash-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))))