Макрос схемы — разверните список в набор вызовов функций

Эта процедура определения того, что ряд крестиков-ноликов помечен, не работает (строка 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.

Спасибо!

Какую схему вы используете?

Shawn 21.12.2020 02:29

я использую гош

Volodymyr Prokopyuk 21.12.2020 09:06

Это не макрос, это процедура, которая создает список '(or (row-marked ....

molbdnilo 21.12.2020 09:42

Есть ли способ сделать список исполняемым без использования eval? Моя цель - избежать повторения кода и автоматически генерировать исполняемое выражение (or ...), сохраняя при этом короткое замыкание как or, так и every-ec.

Volodymyr Prokopyuk 21.12.2020 10:12

Да, это можно сделать с помощью макроса.

molbdnilo 21.12.2020 10:54
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
89
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

То, что вам нужно, это не макрос (и, как вы указали, это не может быть сделано макросом), это 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? ..., но как этот список сделать исполняемым с помощью макроса — это еще вопрос.

Volodymyr Prokopyuk 21.12.2020 15:35

Я добавил дополнение, объясняющее, почему макрос не может быть использован здесь в любом полезном случае.

user5920214 21.12.2020 17:34

Большое спасибо за объяснение и за то, что вы подчеркнули тот факт, что существует большая разница между исходным кодом, который можно преобразовать с помощью макроса, и значениями переменных исходного кода во время выполнения, которые должны быть преобразованы с помощью процедур, а не макросов! Это действительно полезно и полезно! Спасибо, мужик!

Volodymyr Prokopyuk 22.12.2020 09:04

Другие вопросы по теме