#. 到底是做什么的? (尖点)在 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 宏交互,或者 setf
、let*
、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
函数中遗漏了什么细节。并认为有必要包含整个文件以进行调试。
loop
s 范围是完全常规的。但正如 jkiiski 所说,#.
causes the following form to be evaluated at read time: bar-chars
不受约束。
您的代码非常混乱,我无法确定这样的 read-time 评估是否有任何目的。但几乎可以肯定没有:它的用途相当罕见。
编辑:标题已更新以反映我的问题应该是什么,并希望在遇到相同问题时将其他用户引导到这里。
有点乱,但这是 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 宏交互,或者 setf
、let*
、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
函数中遗漏了什么细节。并认为有必要包含整个文件以进行调试。
loop
s 范围是完全常规的。但正如 jkiiski 所说,#.
causes the following form to be evaluated at read time: bar-chars
不受约束。
您的代码非常混乱,我无法确定这样的 read-time 评估是否有任何目的。但几乎可以肯定没有:它的用途相当罕见。