如何在 Scheme 中使用语法规则从列表创建列表?
How to create Alist from List using syntax-rules in Scheme?
正如我要改造的练习:
(alist "foo" 1 "bar" 2 "baz" 3)
进入
(("foo" . 1) ("bar" . 2) ("baz" . 3))
语法规则是否可行?
我的尝试:
(define-syntax alist
(syntax-rules ()
((_ a b) (cons a b))
((_ x y ...)
(list (alist x y) ...))))
扩展成的问题:
(("foo" . 2) ("foo" . "bar") ("foo" . 4) ("foo" . "baz") ("foo" . 6))
语法规则是否可以使用宏列表?它应该是什么样子?
编辑:
再次尝试
(define-syntax alist
(syntax-rules ()
((_ a b) (cons a b))
((_ x y z ...)
(list (alist x y) (alist z ...)))))
它returns (("foo" . 2) (("bar" . 4) ("baz" . 6)))
.
我已经弄明白了:
(define-syntax alist
(syntax-rules ()
((_) ())
((_ a b) (list (cons a b)))
((_ x y z ...)
(apply list (cons x y) (alist z ...)))))
和简化版:
(define-syntax alist
(syntax-rules ()
((_) ())
((_ a b) (list (cons a b)))
((_ x y z ...)
(cons (cons x y) (alist z ...)))))
如果它只是文字(比如 "foo"
和 2
),你可以这样做:
#!r6rs
(import (rnrs))
(define-syntax alist
(syntax-rules (alist-builder)
((_ alist-builder () (results ...))
'(results ...))
((_ alist-builder (a) . rest)
(raise 'bad-alist))
((_ alist-builder (a b rest ...) (results ...))
(alist alist-builder (rest ...) (results ... (a . b))))
((_ a ...) (alist alist-builder (a ...) ()))))
(alist) ; ==> ()
(alist "a" 2) ; ==> (("a" . 2))
(alist a 3 b 4) ; ==> ((a . 3) (b . 4))
(alist a) ; ==> uncaught exception: bad-alist
当然你不能改变这个,因为(alist a b c d)
和字面上写的'((a . b) (c . d))
是一样的,你不能改变。
此外,如果您使用 alist-builder
作为第一个键创建一个列表,内部结构就会泄漏。您可以通过拆分内部定义来解决此问题,并且可以通过将两者都放在库中并仅导出 alist
来隐藏它以免暴露
正如我要改造的练习:
(alist "foo" 1 "bar" 2 "baz" 3)
进入
(("foo" . 1) ("bar" . 2) ("baz" . 3))
语法规则是否可行?
我的尝试:
(define-syntax alist
(syntax-rules ()
((_ a b) (cons a b))
((_ x y ...)
(list (alist x y) ...))))
扩展成的问题:
(("foo" . 2) ("foo" . "bar") ("foo" . 4) ("foo" . "baz") ("foo" . 6))
语法规则是否可以使用宏列表?它应该是什么样子?
编辑:
再次尝试
(define-syntax alist
(syntax-rules ()
((_ a b) (cons a b))
((_ x y z ...)
(list (alist x y) (alist z ...)))))
它returns (("foo" . 2) (("bar" . 4) ("baz" . 6)))
.
我已经弄明白了:
(define-syntax alist
(syntax-rules ()
((_) ())
((_ a b) (list (cons a b)))
((_ x y z ...)
(apply list (cons x y) (alist z ...)))))
和简化版:
(define-syntax alist
(syntax-rules ()
((_) ())
((_ a b) (list (cons a b)))
((_ x y z ...)
(cons (cons x y) (alist z ...)))))
如果它只是文字(比如 "foo"
和 2
),你可以这样做:
#!r6rs
(import (rnrs))
(define-syntax alist
(syntax-rules (alist-builder)
((_ alist-builder () (results ...))
'(results ...))
((_ alist-builder (a) . rest)
(raise 'bad-alist))
((_ alist-builder (a b rest ...) (results ...))
(alist alist-builder (rest ...) (results ... (a . b))))
((_ a ...) (alist alist-builder (a ...) ()))))
(alist) ; ==> ()
(alist "a" 2) ; ==> (("a" . 2))
(alist a 3 b 4) ; ==> ((a . 3) (b . 4))
(alist a) ; ==> uncaught exception: bad-alist
当然你不能改变这个,因为(alist a b c d)
和字面上写的'((a . b) (c . d))
是一样的,你不能改变。
此外,如果您使用 alist-builder
作为第一个键创建一个列表,内部结构就会泄漏。您可以通过拆分内部定义来解决此问题,并且可以通过将两者都放在库中并仅导出 alist