【问题标题】:Common Lisp generate variable names in a macroCommon Lisp 在宏中生成变量名
【发布时间】:2019-06-22 13:06:45
【问题描述】:

我目前正在学习 Common Lisp,作为该过程的一部分,我正在尝试实现一个通用的井字游戏,其中棋盘可以是任何奇数大小(所以有一个中心正方形)。我到了我正在检查获胜者的地方,并且正在使用这个函数来检查行或列是否有获胜者。

(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)))

格式调用最终将被替换为检查播放器是否为零且计数等于大小。无论如何,我想用宏替换这两个 if。所以,它会是这样的

(check row start step)

宏会生成 if 语句

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

然后使用 (check col step start) 调用相同的宏。我似乎无法让宏从行生成行数和行播放器。你会怎么做?

【问题讨论】:

  • 如果编程的话,这不是一种非常 Lisp 的方式。
  • 这里为什么需要宏?只需将其设为函数并像往常一样传递数据即可。如果使用不当,宏会使您的代码更难理解。
  • 我知道这是一种相当愚蠢的做事方式。我故意做一些奇怪的事情来应对我不知道如何用语言做的情况。这里没有充分的理由使用宏,但我想知道怎么做。
  • 您至少可以使用 emacs 并正确缩进您的代码(即像 emacs 一样)。另外,您是否缺少do?我在indented version 中添加了一个。

标签: common-lisp


【解决方案1】:

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

(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))))

虽然已特别注意宏和您的代码最终位于不同的包中并使用所提供符号的包,但如果使用不同的阅读器设置读取文件,它将无法正常工作。如果您编译一个但不编译另一个,它可能无法正常工作。

【讨论】:

  • 我还在学习所有循环可以做什么。我没有意识到你可以在循环本身内完成所有这些。很高兴知道!
  • @Rich 网上有一本免费的 CL 书籍,其中有一章名为 LOOP for black belts,我实际上打开它并定期使用它。此外,Land of Lisp 这本书有一个很棒的页面,名为The periodic table of the LOOP macro,仅此就足以购买这本书。
  • 这是循环周期表的高分辨率源 (PDF)。
猜你喜欢
  • 1970-01-01
  • 2020-09-18
  • 2016-02-17
  • 2018-09-06
  • 2021-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多