Common lisp 公共Lisp在宏中生成变量名

Common lisp 公共Lisp在宏中生成变量名,common-lisp,Common Lisp,我目前正在学习CommonLisp,作为这一过程的一部分,我正在尝试实现一个通用的tic-tac-toe游戏,其中棋盘可以是任意奇数大小(因此有一个中心正方形)。我到了我正在检查赢家的地方,正在使用这个函数来检查一行或一列是否有赢家 (defun straight-winner-p (board start size) (let ((row-player (aref board start 0)) (row-count 0) (col-player (aref

我目前正在学习CommonLisp,作为这一过程的一部分,我正在尝试实现一个通用的tic-tac-toe游戏,其中棋盘可以是任意奇数大小(因此有一个中心正方形)。我到了我正在检查赢家的地方,正在使用这个函数来检查一行或一列是否有赢家

(defun straight-winner-p (board start size)
  (let ((row-player (aref board start 0))
        (row-count 0)
        (col-player (aref board 0 start))
        (col-count 0))

    (loop for step from 0 to (- size 1) do

         (if (equal
              (aref board start step)
              row-player)
             (incf row-count))
         (if (equal
              (aref board step start)
              col-player)
             (incf col-count))
         )
    (format t "row ~a, col ~a~%" row-count col-count)))
格式调用最终将替换为检查播放器是否为零,计数是否等于大小。无论如何,我想用一个宏替换两个ifs。所以,它会是这样的

(check row start step)
宏将生成if语句

         (if (equal
              (aref board start step)
              row-player)
             (incf row-count))

然后使用(检查col step start)调用相同的宏。我似乎无法让宏从行生成行计数和行播放器。您将如何做到这一点?

当您已经使用循环宏时,如何使用循环宏中的功能

(defun straight-winner-p (board start size)
  (loop :with row-player := (aref board start 0)
        :and col-player := (aref board 0 start)
        :for step :below size
        :count (equal (aref board start step) row-player) :into row-count
        :count (equal (aref board step start) col-player) :into col-count
        :finally (format t "row ~a, col ~a~%" row-count col-count)
                 (return (or (= row-count size) (= col-count size)))))
你如何做你想做的事:

(defmacro check (prefix start step)
  (let ((player (intern (concatenate 'string (string prefix) (string '-player)) (symbol-package prefix)))
        (count (intern (concatenate 'string (string prefix) (string '-count)) (symbol-package prefix))))
    `(when (equal (aref board ,start ,step) ,player)
       (incf ,count))))

如果宏和代码最终出现在不同的包中,并使用所提供符号的包,则需要特别小心。如果文件是以不同的读卡器设置读取的,则无法工作。如果编译一个而不是另一个,则可能无法工作

如果编程的话,这不是一种非常Lisp’ish的方式。为什么这里需要一个宏?只需将其作为一个函数,并像往常一样传递数据。如果使用不当,宏会使代码更难理解。我知道这是一种相当愚蠢的方法。我故意做一些奇怪的事情,以应对我不知道如何用这种语言处理的情况。这里没有很好的理由使用宏,但我想知道怎么做。你至少可以使用emacs并正确地缩进你的代码(比如像emacs那样)。另外,您是否缺少一个
do
?我在我的应用程序中添加了一个。我仍在学习所有循环可以做什么。我不知道你可以在循环中完成所有这些。很高兴知道@Rich网上有一本免费的CL书籍,有一章叫做,我实际上打开它并经常使用它。此外,这本书还有一个很好的页面,名为,这就是购买这本书的理由。