方案宏 - 将列表扩展为一组函数调用
Scheme macro - Expand a list into a set of function calls
此识别井字游戏行是否已标记的过程不起作用(X _ _ 行在未标记时被识别为完全标记)
(define (won? b m)
(define (row-marked? r)
(every?-ec (:vector c (index i) b) (if (memv i r)) [char=? c m]))
"Returns #t if the mark m won"
(let ([rr '((0 1 2) (3 4 5) (6 7 8) (0 3 6) (1 4 7) (2 5 8) (0 4 8) (2 4 6))])
`(or ,@(map (lambda (r) `(row-marked? (list ,@r))) rr))))
下面的过程有效
(define (won? b m)
(define (row-marked? r)
(every?-ec (:vector c (index i) b) (if (memv i r)) [char=? c m]))
"Returns #t if the mark m won"
(or (row-marked? '(0 1 2)) (row-marked? '(3 4 5)) (row-marked? '(6 7 8))
(row-marked? '(0 3 6)) (row-marked? '(1 4 7)) (row-marked? '(2 5 8))
(row-marked? '(0 4 8)) (row-marked? '(2 4 6))))
我尝试过,但没有成功
(let ([rr '((0 1 2) (3 4 5) (6 7 8) (0 3 6) (1 4 7) (2 5 8) (0 4 8) (2 4 6))])
`(or ,@(map (lambda (r) `(row-marked? ,r)) rr)))
和
(let ([rr '((0 1 2) (3 4 5) (6 7 8) (0 3 6) (1 4 7) (2 5 8) (0 4 8) (2 4 6))])
`(or ,@(map (lambda (r) `(row-marked? ',r)) rr)))
还有。我做错了什么?
我的目标是避免代码重复并自动生成可执行的 (or ...)
表达式,同时保持 or
和 every-ec
的短路
谢谢!
您需要的不是宏(正如您指定的那样,宏无法完成),而是 SRFI 1's any
函数:
(define (won? b m)
(define (row-marked? r)
(every?-ec (:vector c (index i) b) (if (memv i r)) [char=? c m]))
"Returns #t if the mark m won"
(any row-marked?
'((0 1 2) (3 4 5) (6 7 8) (0 3 6) (1 4 7) (2 5 8) (0 4 8) (2 4 6))))
any
的单列表版本,这就是你所需要的,非常容易编写:
(define (any/1 p l)
(if (null? l)
#f
(or (p (first l))
(any/1 p (rest l)))))
一个成熟的 any
有点难做对,特别是如果你希望它在简单的情况下高效。
也许值得看看为什么您想要实现的目标不能用宏来完成。如果你考虑片段
(let ([rr ...])
(m row-marked? rr))
那么m
可以是展开为(or (row-marked ...) ...)
的宏吗?不,不可能,因为宏转换 source code 并且绑定到 rr
的列表在 运行 之前不可用:宏不有它需要转换的源代码。
真的,你想在这里避免的事情是 row-marked?
正文中的形式应该只被计算多次,直到它们 return 为真,以及这样做的机制只是将它们包装在一个函数中,并根据需要多次调用它。
然而,这种机制有时在语法上有点笨拙:如果我有类似
(any (λ (e1 e2)
(and (integer? e1) (integer? e2)
(even? e1) (even? e2))
(not (= e1 e2)))
l1 l2)
我宁愿这样写
(finding-first ((e1 l1) (e2 l2))
(and (integer? e1) (integer? e2)
(even? e1) (even? e2)
(not (= e1 e2))))
当然,您可以:
(define-syntax finding-first
(syntax-rules ()
[(_ ((v l) ...) form ...)
(any (λ (v ...) form ...) l ...)]))
此识别井字游戏行是否已标记的过程不起作用(X _ _ 行在未标记时被识别为完全标记)
(define (won? b m)
(define (row-marked? r)
(every?-ec (:vector c (index i) b) (if (memv i r)) [char=? c m]))
"Returns #t if the mark m won"
(let ([rr '((0 1 2) (3 4 5) (6 7 8) (0 3 6) (1 4 7) (2 5 8) (0 4 8) (2 4 6))])
`(or ,@(map (lambda (r) `(row-marked? (list ,@r))) rr))))
下面的过程有效
(define (won? b m)
(define (row-marked? r)
(every?-ec (:vector c (index i) b) (if (memv i r)) [char=? c m]))
"Returns #t if the mark m won"
(or (row-marked? '(0 1 2)) (row-marked? '(3 4 5)) (row-marked? '(6 7 8))
(row-marked? '(0 3 6)) (row-marked? '(1 4 7)) (row-marked? '(2 5 8))
(row-marked? '(0 4 8)) (row-marked? '(2 4 6))))
我尝试过,但没有成功
(let ([rr '((0 1 2) (3 4 5) (6 7 8) (0 3 6) (1 4 7) (2 5 8) (0 4 8) (2 4 6))])
`(or ,@(map (lambda (r) `(row-marked? ,r)) rr)))
和
(let ([rr '((0 1 2) (3 4 5) (6 7 8) (0 3 6) (1 4 7) (2 5 8) (0 4 8) (2 4 6))])
`(or ,@(map (lambda (r) `(row-marked? ',r)) rr)))
还有。我做错了什么?
我的目标是避免代码重复并自动生成可执行的 (or ...)
表达式,同时保持 or
和 every-ec
谢谢!
您需要的不是宏(正如您指定的那样,宏无法完成),而是 SRFI 1's any
函数:
(define (won? b m)
(define (row-marked? r)
(every?-ec (:vector c (index i) b) (if (memv i r)) [char=? c m]))
"Returns #t if the mark m won"
(any row-marked?
'((0 1 2) (3 4 5) (6 7 8) (0 3 6) (1 4 7) (2 5 8) (0 4 8) (2 4 6))))
any
的单列表版本,这就是你所需要的,非常容易编写:
(define (any/1 p l)
(if (null? l)
#f
(or (p (first l))
(any/1 p (rest l)))))
一个成熟的 any
有点难做对,特别是如果你希望它在简单的情况下高效。
也许值得看看为什么您想要实现的目标不能用宏来完成。如果你考虑片段
(let ([rr ...])
(m row-marked? rr))
那么m
可以是展开为(or (row-marked ...) ...)
的宏吗?不,不可能,因为宏转换 source code 并且绑定到 rr
的列表在 运行 之前不可用:宏不有它需要转换的源代码。
真的,你想在这里避免的事情是 row-marked?
正文中的形式应该只被计算多次,直到它们 return 为真,以及这样做的机制只是将它们包装在一个函数中,并根据需要多次调用它。
然而,这种机制有时在语法上有点笨拙:如果我有类似
(any (λ (e1 e2)
(and (integer? e1) (integer? e2)
(even? e1) (even? e2))
(not (= e1 e2)))
l1 l2)
我宁愿这样写
(finding-first ((e1 l1) (e2 l2))
(and (integer? e1) (integer? e2)
(even? e1) (even? e2)
(not (= e1 e2))))
当然,您可以:
(define-syntax finding-first
(syntax-rules ()
[(_ ((v l) ...) form ...)
(any (λ (v ...) form ...) l ...)]))