我是Haruo。我的荣幸是解决Common Lisp(CLISP)中的SPOJ。今天我解决了古典/障碍!但在SBCL中不是CLISP。由于运行时错误(NZEC),我的CLISP提交失败。
我希望我的代码变得更加复杂。今天的问题只是一个机会。请遵循以下代码,并告诉我您的重构策略。我相信你。
春男
答案 0 :(得分:4)
以get-x-depth-for-yz-grid
为例。
(defun get-x-depth-for-yz-grid (planes//yz-plane grid)
(let ((planes (get-planes-including-yz-grid-in planes//yz-plane grid)))
(unless (evenp (length planes))
(error "error in get-x-depth-for-yz-grid"))
(sort planes (lambda (p1 p2) (< (caar p1) (caar p2))))
(do* ((rest planes (cddr rest)) (res 0))
((null rest) res)
(incf res (- (caar (second rest)) (caar (first rest)))))))
样式-> ERROR可以用ASSERT代替。
可能的错误-> SORT可能具有破坏性->确保您拥有一份新鲜的清单!如果它已经由get-planes-including-yz-grid-in
分配了,那么我们不需要。
错误-> SORT返回排序列表。排序的列表可能不是副作用。 ->使用返回的值
样式->用LOOP代替。
样式-> CAAR的含义不清楚。查找更好的命名或使用其他数据结构。
(defun get-x-depth-for-yz-grid (planes//yz-plane grid)
(let ((planes (get-planes-including-yz-grid-in planes//yz-plane grid)))
(assert (evenp (length planes)) (planes)
"error in get-x-depth-for-yz-grid")
(setf planes (sort (copy-list planes) #'< :key #'caar))
(loop for (p1 p2) on planes by #'cddr
sum (- (caar p2) (caar p1)))))
答案 1 :(得分:2)
->
宏会混淆sbcl的类型推断。您应该将(-> x)
扩展为x
,将(-> x y...)
扩展为(let (($ x)) (-> y...))
loop
,并在更多地方使用它。发生额外突变的dolist
不好destructuring-bind
而不是(rest (rest ))
。您也不一致,有时您会为此写(cddr...)
。block*
遇到许多问题:
(let (foo) (setf foo...))
来触发sbcl类型推断。block*
意味着各种绑定的范围都可以引用以前定义的东西,但实际上所有初始值都可以引用任何变量或函数名称,并且该变量尚未初始化。然后计算结果为零。get-x-y-and-z-ranges
确实需要使用loop
。我认为也是错的:列表的长度不同。first
等。甚至可能是struct(!)(sort foo)
可能会破坏foo
。您需要执行(setf foo (sort foo))
。do
。使用loop
。:key
。defvar
,但我想您的意思是defparameter
*t*
是一个愚蠢的名字