【问题标题】:scheme aliases for macros宏的方案别名
【发布时间】:2018-07-14 01:16:27
【问题描述】:

如何在 Scheme 中为宏创建别名?

与 Clojure 的思路相同

define a synonym for a Clojure macro

这适用于 Common Lisp

common lisp function/macro aliases

我意识到它是功能

(define alias function)

但我似乎找不到或想出如何为宏定义别名(准确地说是在 GNU Guile 中)

【问题讨论】:

    标签: clojure macros scheme lisp


    【解决方案1】:

    如果您使用支持 R6RS 的方案实现,例如 Chez Scheme 或 guile,最简单的方法是使用标识符语法创建别名:

    (define-syntax new-name (identifier-syntax old-name))
    

    identifier-syntax 不仅可以为名称取别名:它还可以为表达式取别名。所以你可以定义一个**未指定**宏,如下所示:

    (define-syntax **unspecified** (identifier-syntax (if #f #f)))
    

    【讨论】:

      【解决方案2】:

      Guile 支持语法规则,因此为“and”创建别名的合理方法如下所示:

      ;; define my-and as an alias for and:
      (define-syntax my-and   
        (syntax-rules ()
          [(_ arg ...)
           (and arg ...)]))
      
      ;; try it out:
      (display (my-and #t #t)) (newline)
      (display (my-and #t #f)) (newline)
      (display (my-and #f (/ 1 0))) (newline)
      

      如果你真的想要一个语法别名形式,你可以... 惊喜! ... 将它定义为一个宏:

      ;; define a 'syntax-alias' form
      (define-syntax syntax-alias
        (syntax-rules ()
          [(_ newname oldname)
           (define-syntax newname
             (syntax-rules ()
               [(_ arg (... ...))
                (oldname arg (... ...))]))]))
      
      ;; use 'syntax-alias' to define 'my-and' as an alias for 'and':
      (syntax-alias my-and and)
      
      ;; try it out:
      (display (my-and #t #t)) (newline)
      (display (my-and #t #f)) (newline)
      (display (my-and #f (/ 1 0))) (newline)
      

      【讨论】:

      • 您的解决方案很优雅,可能解决了 OP 问题。但是,还应注意,您定义的是 new 宏,而不是真正的 aliases(即新的“名称”“引用”旧的宏)。
      • 我肯定在定义一个宏。我的猜测是,对于什么是“真正的别名”,并没有很好的语言级别定义……
      【解决方案3】:

      在 R5RS 的可移植 Scheme 中,您需要创建一个宏来实现它:

      (define-syntax test 
        (syntax-rules ()
          ((_ . args) (if . args))))
      

      这有点冗长,因此您可以创建一个宏来为您执行此操作:

      (define-syntax define-syntax-alias
        (syntax-rules ()
          ((_ new-name old-name)
           (define-syntax new-name
             (syntax-rules ()
               ((_ . args) (old-name . args)))))))
      
      (define-syntax-alias test if)
      

      当然,define-syntax-alias 的实现可以放在它自己的库中,并在 R6RS 及更高版本需要它的任何地方重用。

      在一个相关的方言 Racket 中,它以 Scheme 开始,但现在已经分化成它自己的 lisp 语言,你在标准语言中有这样的东西:

      (define-syntax test (make-rename-transformer #'if))
      

      【讨论】:

      • 我认为还应该注意的是,在 Racket 中,重命名函数和宏的最简单方法是使用(require (rename-in ....))。对于上面将iftest 混淆的示例,它将是(require (rename-in racket/base (if test))
      • @DiiP 这适用于整个文件,但是您可以在本地使用重命名转换器。例如。在 Greg 的 Fear of Macros he uses it in aif 中,您不能用导入替换它。
      猜你喜欢
      • 2013-01-18
      • 1970-01-01
      • 2023-04-02
      • 2018-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-22
      相关资源
      最近更新 更多