编辑:标题更新,以反映我的问题应该是什么,并希望引导其他用户在他们有同样的问题。
有点混乱,但这是任何骰子正在进行的通用lisp实现,它应该输出一些ascii技术,表示表示骰子卷的散列表的概率密度函数。我一直在试图找出确切的原因,但是当我试图在clisp中运行文件时,我一直得到错误的clisp。错误源于output函数。
代码是混乱和复杂的(但以前如果用更简单的方法替换output的内部最循环),但是这个特定的错误对我来说没有意义。是否允许我访问外部let*变量/绑定/从内部最内部循环/cond访问任何东西?即使我直接用bar-chars代替list表单,我也会得到另一个错误,即char-十进制也没有值。我确信循环宏与我所缺少的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程序,所以我并不想要任何关于格式化/风格/性能/设计/等等的批评,因为我知道这一切都会更好。只是好奇我在导致错误的output函数中遗漏了什么细节。并认为有必要为调试目的包括整个文件。
发布于 2022-06-02 16:19:50
loop的范围界定是完全传统的。但正如jkiiski所说,时间:bar-chars那时不受约束。
您的代码非常混乱,因此我无法确定像这样读取时间评估是否有任何意义。但几乎可以肯定没有:它的用途是相当罕见的。
https://stackoverflow.com/questions/72472872
复制相似问题