【问题标题】:How to create Alist from List using syntax-rules in Scheme?如何使用 Scheme 中的语法规则从 List 创建一个 List?
【发布时间】:2020-11-03 08:52:35
【问题描述】:

就像我想改造的练习:

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

可以使用语法规则来实现宏 alist 吗?它应该是什么样子?

编辑:

又一次尝试

(define-syntax alist
  (syntax-rules ()
     ((_ a b) (cons a b))
     ((_ x y z ...)
      (list (alist x y) (alist z ...)))))

它返回(("foo" . 2) (("bar" . 4) ("baz" . 6)))。

【问题讨论】:

    标签: macros scheme hygiene


    【解决方案1】:

    我已经弄清楚了:

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

    【讨论】:

    • 请注意,您可以使用cons 而不是apply list:cons 更简单
    【解决方案2】:

    如果只是文字(如"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

    来隐藏它

    【讨论】:

    • 你能告诉我为什么这比我的代码更好,更简单吗?是因为它有错误处理吗?在我的代码中,我可以在 cons 中使用 'a 和 'x,它也适用于 (alist a 3 b 4)。
    • @jcubic 他们的工作方式不同。您的版本会创建评估为 alist 的代码。我的在编译时创建常量文字。如果您在程序中使用它,您将使用您的版本一次又一次地重新创建相同的列表,它将是不变的文字,并且使用我的版本制作一次。此外,您版本中的(alist) 会变成无效的方案代码()。它应该发出错误信号。
    • 感谢您的解释,这对我来说是新事物,因为我测试它并尝试了解它的工作原理的方式是我实现的语法规则,它在运行时进行评估。我需要重写它并为我的 lisp 添加扩展时间。
    猜你喜欢
    • 2010-12-07
    • 2022-10-13
    • 2015-09-03
    • 2022-08-19
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 2021-05-22
    相关资源
    最近更新 更多