【问题标题】:How to map a macro over a list - or - How to use macros to define data types如何在列表上映射宏 - 或 - 如何使用宏定义数据类型
【发布时间】:2012-05-23 23:07:27
【问题描述】:

我喜欢用我自己的数据类型构建一个 REPL,但我不喜欢一遍又一遍地编写所有相同的模式函数。

所以这是一个疯子,这让我很困扰。

我有自己的一组原始数据类型(define primitives '("mytrue" "myfalse" "mynumber" ...))

我还有(define primitiveTesters (list "mytrue?" "myfalse?" "mynumber?" ... )

现在的问题是,我只想应用(映射)或宏来获取数据类型?程序,它基本上只是检查记录的汽车 (mynumber . ( . )) 是否存在。

最后类似于(mynumber? (car (mynumber.(1.))) => #t。但为此我需要(define mynumber? (lambda (...)(...))

我的定义批处理宏看起来像这样,但我只是没有运气注入<variable>

(define-syntax define-batching
(syntax-rules () 
((_ value expr)(define value expr))
((_ value) value)
((_ value1 value2 ...)  (begin (define value1 expr) (define-batching test2...)))
))

那么我是不是走到了死胡同?

我在 Emacs Lisp 中看到过类似的东西。

我到底要找的是:

 (define checker '(audi? volkswagen? mercedes?))
 (define datatype '(audi volkswagen mercedes))

 (map define-checker checker datatype )
 or
 (define-checker (car checker) (car datatype))

【问题讨论】:

  • 关于 (map define-checker checker datatype ) 你不能在列表上映射宏。在 (define-checker (car checker) (car datatype)) 中,假设 define-checker 是一个宏,扩展发生在 compile-time 那里,因为 checker 还没有值。这发生在运行时。如果您需要在编译时获得列表值(与语法对象相反,那么您需要查看更高级的宏系统。但请参阅下面我的答案的附录。

标签: macros scheme read-eval-print-loop r5rs


【解决方案1】:

如果我对问题的理解正确,您需要一个宏 定义自己的类型检查器?

这是一种方法:

(define-syntax define-checker
  (syntax-rules ()
    [(define-checker name tag)
     (define (name object)
       (and (list? object)
            (not (null? object))
            (eq? (car object) 'tag)))]))

(define-checker my-car? car)

(my-car? '(car audi black))   ; evaluates to #t
(my-car? '(truck ford pink))  ; evaluates to #f

附录:

如果你写

(define checker '(audi? volkswagen? mercedes?))
(define datatype '(audi volkswagen mercedes))

这些值将在运行时可用。 因此,您需要采用不同的方法。

例如你可以写:

(define-checker+datatype (audi? audi) (volkswagen? volkswagen?))

代码如下:

(define-syntax define-checker
  (syntax-rules ()
    [(define-checker name tag)
     (define (name object)
       (and (list? object)
            (not (null? object))
            (eq? (car object) 'tag)))]))


(define-syntax define-checkers+datatype
  (syntax-rules ()
    [(define-checkers+datatype (name tag) ...)
     (begin
       (define-checker name tag)
       ...)]))

(define-checkers+datatype (audi? audi) (wv? wv))


(audi? '(audi black))

【讨论】:

  • 好的,我明白了。您提供的绝佳选择。非常感谢支持。
【解决方案2】:

define-syntax 是卫生的,也就是说它不会影响父环境,也就是说它不能在其中定义符号。 您可以尝试使用 er-、ir- 宏转换器,它们允许您显式重命名符号。

在你的方案文档中谷歌的关键字是“er-macro-transformet”和“ir-macro-transformer”

【讨论】:

  • 关于syntax-rules; define 在宏中没有任何问题,特别是在这种情况下,value 标识符是由用户传入的,因此定义将可见。
  • syntax-rules 是卫生的,但 syntax-case 转换器会创建不卫生的宏。您可以使用 datum->syntax 引入新符号来破坏卫生。
猜你喜欢
  • 2011-02-08
  • 2012-09-07
  • 2018-07-03
  • 2012-09-07
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
相关资源
最近更新 更多