在Scheme中定义一个宏来创建花式子列表

时间:2015-12-12 11:46:49

标签: functional-programming macros scheme racket

我想解决有关宏的问题:

  

定义此构造:   (subl e_1 e_2 ... -> e_i ... e_j <- e_j+1 ... e_n);   其评估返回子列表(e_i ... e_j)。   例如。 (subl 1 -> 2 3 4 <- 5 6)应为(2 3 4)

我试图解决它(以下是部分解决方案)但它没有用......

(define-syntax subl
  (syntax-rules(> <)
    ((_  x y ... > x ... y < c v )
     (begin
       '(x y)))))

错误是:

  

语法规则:模式中错位的省略号(遵循其他省略号)   在:......

3 个答案:

答案 0 :(得分:4)

你不能在一对括号中使用多个省略号,如果你使用的是关键词-><-,那么这并不重要,语言不够聪明,不知道在哪里停止扩张。

示例:
(_ x ...)是合法的,x ...会抓住所有内容,直到结束时 (_ x y ... z)是合法的,x与开头的单个元素匹配,y ...捕获所有内容,但最后一个元素z与最后的单个元素匹配。
(_ (x ...) y ...)是合法的,x ...捕获内括号内的所有内容,并y ...在外括号内进行任务。
(_ x ... y ...) 合法,因为您无法说明扩展这两个群组的距离。

所以你必须分多步解决问题:删除->之前的元素,删除<-之后的元素,最后捕获中间的列表。

(define-syntax subl
  (syntax-rules (-> <-)
    ((_ -> x ... <-)
     '(x ...))
    ((_ -> x ... y)
     (subl -> x ...))
    ((_ x y ...)
     (subl y ...))))

答案 1 :(得分:2)

您需要创建将您的源转换为更简单的处理模式:

(define-syntax subl
  (syntax-rules (-> <-)
    ((_ "build-list" end middle before)
     (subl "execute" before middle end))
    ((_ "build-list" before () () -> . rest)
     (subl "build-list" () () before . rest ))
    ((_ "build-list" middle () before <- . rest)
     (subl "build-list" () middle before . rest ))
    ((_ "build-list" (xs ...) the others x . rest)
     (subl "build-list" (xs ... x) the others . rest))
    ((_ "execute" before middle end)
     ; I guess this is wrong
     'middle)
    ((_ . rest)
     (subl "build-list" () () () . rest))))

(subl a b c -> d e f <- f g) ; == '(d e f) => (d e f)

更改您希望代码更简单的格式是什么? (subl a b c -> d e f <- f g) => (subl "execute" (a b c) (d e f) (f g))然后您在“执行”模式中拥有所需的逻辑。

答案 2 :(得分:1)

您可以使用Racket syntax-parse实现您的宏(因为您包含了标记:)),它具有比#lang racket (require (for-syntax syntax/parse)) (define-syntax (subl stx) (syntax-parse stx #:datum-literals (-> <-) [(_ a b ... -> c ... d <- e ... f) #:when (printf "a: ~a\n" (syntax->datum #'a)) #:when (printf "bs: ~a\n" (syntax->datum #'(b ...))) #:when (printf "cs: ~a\n" (syntax->datum #'(c ...))) #:when (printf "d: ~a\n" (syntax->datum #'d)) #:when (printf "es: ~a\n" (syntax->datum #'(e ...))) #:when (printf "f: ~a\n" (syntax->datum #'f)) #''(c ... d)])) (subl 1 -> 2 3 4 <- 5 6) 更具表现力的模式语言。

a: 1
bs: ()
cs: (2 3)
d: 4
es: (5)
f: 6
'(2 3 4)

产生

{{1}}