Эта процедура определения того, что ряд крестиков-ноликов помечен, не работает (строка 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
.
Спасибо!
я использую гош
Это не макрос, это процедура, которая создает список '(or (row-marked ...
.
Есть ли способ сделать список исполняемым без использования eval
? Моя цель - избежать повторения кода и автоматически генерировать исполняемое выражение (or ...)
, сохраняя при этом короткое замыкание как or
, так и every-ec
.
Да, это можно сделать с помощью макроса.
То, что вам нужно, это не макрос (и, как вы указали, это не может быть сделано макросом), это SRFI 1 любая функция:
(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 ...) ...)
? Нет, не может быть, потому что макросы преобразуют исходный код, а список, привязанный к rr
, недоступен до времени выполнения: у макроса нет исходного кода, который нужно преобразовать.
На самом деле, чего вы хотите избежать здесь, так это того, что формы в теле row-marked?
должны оцениваться только столько раз, пока они не вернут true, и механизм для этого просто заключает их в функцию и вызывает только как много раз по мере необходимости.
Однако этот механизм иногда немного синтаксически неуклюж: если у меня есть что-то вроде
(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 ...)]))
Спасибо за ответ! Ответ решает проблему, поэтому я приму его, но в ответе не объясняется, как заставить работать код в вопросе. Я понимаю, что процедура в вопросе возвращает список '(or (row-marked? ...
, но как этот список сделать исполняемым с помощью макроса — это еще вопрос.
Я добавил дополнение, объясняющее, почему макрос не может быть использован здесь в любом полезном случае.
Большое спасибо за объяснение и за то, что вы подчеркнули тот факт, что существует большая разница между исходным кодом, который можно преобразовать с помощью макроса, и значениями переменных исходного кода во время выполнения, которые должны быть преобразованы с помощью процедур, а не макросов! Это действительно полезно и полезно! Спасибо, мужик!
Какую схему вы используете?