4

我正在用 CL 编写一个地牢爬行游戏,但我在使用案例表单时遇到了问题。

两件事情:

  • Common Lisp 抱怨Duplicate keyform QUOTE in CASE statement
  • (make-instance 'cl-rogue:tile tile-type 'wall)应该打印为“#”,但无论我使用哪种瓷砖类型,对象都会打印为“”。

编码:

(in-package :cl-user)

(defpackage :cl-rogue
  (:use :common-lisp)
  (:export
    :*rows*
    :*cols*
    :*levels*
    :tile
    :tile-type
    :tile-contents
    :tile-hidden
    :tile-locked
    :tile-closed
    :main))

(in-package :cl-rogue)

(defparameter *cols* 80)
(defparameter *rows* 24)
(defparameter *levels* 26)

班上:

(defclass tile ()
  ((tile-type
    :initarg :tile-type
    :accessor tile-type
    :initform 'floor
    :documentation "Type of tile")
    (tile-contents
      :initarg :tile-contents
      :accessor tile-contents
      :initform '()
      :documentation "Any items the tile holds")
    (tile-hidden
      :initarg :tile-hidden
      :accessor tile-hidden
      :initform nil
      :documentation "Whether the tile is hidden or shown")
    (tile-locked
      :initarg :tile-locked
      :accessor tile-locked
      :initform nil
      :documentation "Whether the tile is locked")
    (tile-closed
      :initarg :tile-closed
      :accessor tile-closed
      :initform nil
      :documentation "Whether the tile is open or closed")))

打印方法:

(defmethod print-object ((object tile) stream)
  (with-slots (tile-type tile-contents tile-hidden tile-locked tile-closed) object
    (if tile-hidden
      (format stream " ")
      (let ((an-item (car tile-contents)))
        (if an-item
          (format stream "~a" an-item)
          (format stream (case tile-type
            ('wall "#")
            ('upstair "<")
            ('downstair ">")
            ('door (if tile-closed "+" "\\"))
            (otherwise " "))))))))
4

1 回答 1

12

您不需要引用 中的符号CASE

不评估 CASE 子句中的符号。

(case tile-type
  (wall ...)
  (door ...))

WALL并且DOOR是纯粹的符号,不作为变量进行评估。

Lisp 阅读器读取'foo(quote foo).

你写了:

(case tile-type
  ('wall ...)
  ('door ...))

相当于:

(case tile-type
  ((quote wall) ...)
  ((quote door) ...))

但是你不能在CASE. 您必须提供符号作为文字常量。

如果你写:

(let ((bar 'foo)
      (baz 'foo))
  (case bar
    (baz :we-have-a-foo-through-baz)
    (foo :we-really-have-a-foo)))

这返回:WE-REALLY-HAVE-A-FOO。因为CASE使用常量数据,而不是变量。

CASE接受项目列表。由于您QUOTE在 more than 子句中有一个符号,因此编译器会显示警告。

正如我所说,不可能引用,因为这些项目没有被评估。

至于CASE接受子句中的项目列表,它看起来像这样:

(case tile-type
  ((door wall) ...)
  ((floor window painting) ...))

对于WALL符号,您需要在创建对象时确保它位于正确的包中。

最好使用关键字符号,例如:wall. 然后您不需要导出它,并且不会混淆符号在哪个包中。

关于代码的格式:您有一个项目符号列表,紧随其后的是代码部分。这没有按照您的预期呈现。我在代码之前添加了文本“代码:”。然后渲染按预期工作。

于 2011-04-01T07:55:36.747 回答