#. 到底是做什么的? (尖点)在 Common Lisp 中做什么?是否导致变量没有值错误?

What exactly does the #. (sharpsign dot) do in Common Lisp? Is it causing a variable has no value error?

编辑:标题已更新以反映我的问题应该是什么,并希望在遇到相同问题时将其他用户引导到这里。

有点乱,但这是 anydice 的 work-in-progress 常见 lisp 实现,它应该输出一些表示概率密度函数的 ascii 艺术 hash-table 表示掷骰子.我一直在试图找出确切原因,但在尝试 运行 clisp 中的文件时,我一直收到错误 *** - SYSTEM::READ-EVAL-READER: variable BAR-CHARS has no value。错误源自 output 函数。

代码混乱且令人费解(但如果 output 的最内层循环被更简单的代码替换,则以前可以正常工作),但这个特定错误对我来说没有意义。我不允许从最里面的 loop/cond 访问外部的 let* variables/bindings/whatever 吗?即使当我直接用 bar-chars 代替列表形式时,我也会收到另一个错误,即 char-decimal 也没有值。我确定循环宏与我缺少的 cond 宏交互,或者 setflet*multiple-value-bind 等之间的区别,但我一直在尝试在没有运气的情况下调试这个特定问题。

(defun sides-to-sequence (sides)
  (check-type sides integer)
  (loop for n from 1 below (1+ sides) by 1 collect n))

(defun sequence-to-distribution (sequence)
  (check-type sequence list)
  (setf distribution (make-hash-table))
  (loop for x in sequence
    do (setf (gethash x distribution) (1+ (gethash x distribution 0))))
  distribution)

(defun distribution-to-sequence (distribution)
  (check-type distribution hash-table)
  (loop for key being each hash-key of distribution
    using (hash-value value) nconc (loop repeat value collect key)))

(defun combinations (&rest lists)
  (if (endp lists)
      (list nil)
      (mapcan (lambda (inner-val)
                (mapcar (lambda (outer-val)
                          (cons outer-val
                                inner-val))
                        (car lists)))
              (apply #'combinations (cdr lists)))))

(defun mapcar* (func lists) (mapcar (lambda (args) (apply func args)) lists))

(defun dice (left right)
  (setf diceprobhash (make-hash-table))
  (cond ((integerp right)
         (setf right-distribution
               (sequence-to-distribution (sides-to-sequence right))))
        ((listp right)
         (setf right-distribution (sequence-to-distribution right)))
        ((typep right 'hash-table) (setf right-distribution right))
        (t (error (make-condition 'type-error :datum right
                                  :expected-type
                                  (list 'integer 'list 'hash-table)))))
  (cond ((integerp left)
         (sequence-to-distribution
          (mapcar* #'+
                   (apply 'combinations
                     (loop repeat left collect
                       (distribution-to-sequence right-distribution))))))
        (t (error (make-condition 'type-error :datum left
                                  :expected-type
                                  (list 'integer))))))

(defmacro d (arg1 &optional arg2)
  `(dice ,@(if (null arg2) (list 1 arg1) (list arg1 arg2))))

(defun distribution-to-probability (distribution)
  (setf probability-distribution (make-hash-table))
  (setf total-outcome-count
        (loop for value being the hash-values of distribution sum value))
  (loop for key being each hash-key of distribution using (hash-value value)
    do (setf (gethash key probability-distribution)
             (float (/ (gethash key distribution) total-outcome-count))))
  probability-distribution)

(defun output (distribution)
  (check-type distribution hash-table)
  (format t "   #  %~%")
  (let* ((bar-chars (list 9617 9615 9614 9613 9612 9611 9610 9609 9608))
    (bar-width 100)
    (bar-width-eighths (* bar-width 8))
    (probability-distribution (distribution-to-probability distribution)))
    (loop for key being each hash-key of
      probability-distribution using (hash-value value)
      do (format t "~4d ~5,2f ~{~a~}~%" key (* 100 value)
                 (loop for i from 0 below bar-width
                       do (setf (values char-column char-decimal)
                                (truncate (* value bar-width)))
                       collect
                       (cond ((< i char-column)
                              #.(code-char (car (last bar-chars))))
                             ((> i char-column)
                              #.(code-char (first bar-chars)))
                             (t
                              #.(code-char (nth (truncate
                                                 (* 8 (- 1 char-decimal)))
                                                bar-chars)))))))))

(output (d 2 (d 2 6)))

这是我一起破解的第一个通用 lisp 程序,所以我真的不想对 formatting/style/performance/design/etc 提出任何批评,因为我知道它可能会更好。只是好奇我在导致错误的 output 函数中遗漏了什么细节。并认为有必要包含整个文件以进行调试。

loops 范围是完全常规的。但正如 jkiiski 所说,#. causes the following form to be evaluated at read time: bar-chars 不受约束。

您的代码非常混乱,我无法确定这样的 read-time 评估是否有任何目的。但几乎可以肯定没有:它的用途相当罕见。