【问题标题】:Common Lisp case and quoted elementsCommon Lisp 大小写和引用元素
【发布时间】:2011-07-27 11:43:45
【问题描述】:

我正在用 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 " "))))))))

【问题讨论】:

    标签: common-lisp case quote


    【解决方案1】:

    CASE 中的符号无需引用。

    不评估 CASE 子句中的符号。

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

    WALLDOOR 是纯符号,不作为变量进行计算。

    Lisp 阅读器读取 'fooas (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 接受项目列表。由于您在 more than 子句中将QUOTE 作为符号,因此编译器会显示警告。

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

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

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

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

    最好使用关键字符号,例如:wall。那么你就不需要导出它了,也不会混淆符号在哪个包中。

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

    【讨论】:

    • @mcandre:无法识别枚举后的代码。您需要先输入一段文字,然后输入代码。
    • 我不知道如何解释。我认为语法是 (case something (this do-this) (that do-that) (otherwise do-otherwise))
    • 这是一个漂亮的答案。
    猜你喜欢
    • 2015-12-22
    • 2011-11-14
    • 2020-09-08
    • 2011-08-16
    • 2019-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-10
    相关资源
    最近更新 更多