common-lisp - 常见的 Lisp 案例和引用元素

标签 common-lisp case quote

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

    最佳答案

    您不需要引用 CASE 中的符号。

    不评估 CASE 子句中的符号。

    (case tile-type
      (wall ...)
      (door ...))
    
    WALLDOOR 纯粹是符号,不作为变量进行评估。

    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 作为多个子句中的符号,因此编译器会显示警告。

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

    至于 CASE 接受子句中的项目列表,它看起来像这样:
    (case tile-type
      ((door wall) ...)
      ((floor window painting) ...))
    

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

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

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

    关于common-lisp - 常见的 Lisp 案例和引用元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5510317/

    相关文章:

    common-lisp - 获取SBCL中的线程ID

    common-lisp - 如何在 Common-Lisp CLOS 中在运行时可移植地创建一个类

    如果数据为 Null 或使用 CASE 语句为空,则 MySQl 查询 UPDATE

    MySQL Case 语句不起作用

    c - 在 C 中打印“(双引号)

    lisp - 符号处理 : cannot compare for identity

    lisp - Common Lisp 类型声明未按预期工作

    sql - 从 PostgreSQL 到 SQL Server 的带有 bool 值的大小写表达式

    javascript - .NET MVC/Javascript 从动态 HTML 转义单引号

    arrays - 普通口齿不清 : value 16777216 is not of the expected type (UNSIGNED-BYTE 24)