Yellow Rabbit

Трилобит как подопытный кролик для простых макросов

Игра Трилобит на Lisp: простейшие макросы

Вообще говоря можно писать на Lisp и при этом не подозревать о макросах. Это тёмное искусство и освоить его тяжко, однако простые вещи вполне можно попробовать.

Делаем вещи короче

Простейшее применение макросов: уменьшение количества строк в коде. Конечно это никак не сделало меньше объектный файл и не ускорило программу. Вообще говоря, если бы макросы могли рассматривать свои аргументы не как формы, то возможна была бы генерация таблиц left-pattern во время компиляции. Надо подумать над этим.


;; ((left...) (right...)
;;  (up...) (down...)
;;  (left-up...) (right-down...)
;;  (left-down...) (right-up))
(defmacro make-pattern (fn)
  `(loop
     repeat (1- *win-len*)
     for i from 1
     collect ,fn))

(defmacro collect-cells (cond pat)
  `(loop
     repeat (min (1- *win-len*) ,cond)
     for off in ,pat
     collect (+ cell off)))

(let 
   ((left-pattern       (make-pattern (- i)))
    (right-pattern      (make-pattern i))
    (up-pattern         (make-pattern (- (* *board-width* i))))
    (down-pattern       (make-pattern (+ (* *board-width* i))))
    (left-up-pattern    (make-pattern (- (* i (1+ *board-width*)))))
    (right-down-pattern (make-pattern (* i (1+ *board-width*))))
    (left-down-pattern  (make-pattern (+ (* i (1- *board-width*)))))
    (right-up-pattern   (make-pattern (- (* i (1- *board-width*))))))
    (defun slow-get-test-patterns (cell)
      (list
        ; left
        (collect-cells (mod cell *board-width*) left-pattern)
        ; right
        (collect-cells (- *board-width* (mod cell *board-width*) 1) right-pattern)
        ; up
        (collect-cells (floor cell *board-width*) up-pattern)
        ; down
        (collect-cells (- *board-height* (floor cell *board-width*) 1) down-pattern)
        ; left-up
        (collect-cells (min (mod cell *board-width*) (floor cell *board-width*)) left-up-pattern)
        ; right-down
        (collect-cells (min
                        (- *board-width* (mod cell *board-width*) 1)
                        (- *board-height* (floor cell *board-width*) 1))
                       right-down-pattern)
        ; left-down
        (collect-cells (min
                        (mod cell *board-width*)
                        (- *board-height* (floor cell *board-width*) 1))
                       left-down-pattern)
        ; right-up
        (collect-cells (min
                        (- *board-width* (mod cell *board-width*) 1)
                        (floor cell *board-width*))
                       right-up-pattern))))