在 Scheme 中定义一个宏来创建花哨的子列表
Defining a macro in Scheme to create fancy sublist
我想解决一个关于宏的问题:
Define this construct:
(subl e_1 e_2 ... -> e_i ... e_j <- e_j+1 ... e_n)
;
its evalutation returns the sublist (e_i ... e_j)
.
E.g. (subl 1 -> 2 3 4 <- 5 6)
should be (2 3 4)
.
我尝试解决了(以下是部分解决方案)但是没有用...
(define-syntax subl
(syntax-rules(> <)
((_ x y ... > x ... y < c v )
(begin
'(x y)))))
错误是:
syntax-rules: misplaced ellipsis in pattern (follows other ellipsis)
in: ...
您需要制作将源代码转换为更易于处理的内容的模式:
(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))
那么您在 "execute" 的模式中就有了您想要的逻辑。
你不能在一对括号中使用多个省略号,如果你使用关键字 ->
和 <-
语言不够聪明,不知道在哪里停止也没关系扩展。
示例:
(_ 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 ...))))
您可以使用 Racket 的 syntax-parse
(since you included the racket 标签来实现您的宏 :)),它具有比 syntax-rules
.
更具表现力的模式语言
#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)
我想解决一个关于宏的问题:
Define this construct:
(subl e_1 e_2 ... -> e_i ... e_j <- e_j+1 ... e_n)
; its evalutation returns the sublist(e_i ... e_j)
. E.g.(subl 1 -> 2 3 4 <- 5 6)
should be(2 3 4)
.
我尝试解决了(以下是部分解决方案)但是没有用...
(define-syntax subl
(syntax-rules(> <)
((_ x y ... > x ... y < c v )
(begin
'(x y)))))
错误是:
syntax-rules: misplaced ellipsis in pattern (follows other ellipsis) in: ...
您需要制作将源代码转换为更易于处理的内容的模式:
(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))
那么您在 "execute" 的模式中就有了您想要的逻辑。
你不能在一对括号中使用多个省略号,如果你使用关键字 ->
和 <-
语言不够聪明,不知道在哪里停止也没关系扩展。
示例:
(_ 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 ...))))
您可以使用 Racket 的 syntax-parse
(since you included the racket 标签来实现您的宏 :)),它具有比 syntax-rules
.
#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)