【问题标题】:some strategies to refactor my Common Lisp code重构我的 Common Lisp 代码的一些策略
【发布时间】:2018-07-13 22:45:06
【问题描述】:

我是春雄。我很高兴在 Common Lisp(CLISP) 中解决 SPOJ。今天我解决了古典/巴尔克!但在 SBCL 中不是 CLISP。由于运行时错误 (NZEC),我的 CLISP 提交失败。

我希望我的代码变得更加复杂。今天的问题只是一个机会。请按照我的代码告诉我你的重构策略。我相信你。

https://github.com/haruo-wakakusa/SPOJ-ClispAnswers/blob/0978813be14b536bc3402f8238f9336a54a04346/20040508_adrian_b.lisp

春男

【问题讨论】:

标签: common-lisp clisp


【解决方案1】:

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)))))))

style -> ERROR 可以替换为 ASSERT。

可能的错误 -> SORT 可能具有破坏性 -> 确保你有一个新的列表!如果它已经是由get-planes-including-yz-grid-in 分配的,那么我们不需要它。

bug -> SORT 返回一个排序列表。排序列表可能不是副作用。 -> 使用返回值

style -> DO 替换为 LOOP。

style -> 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)))))

【讨论】:

    【解决方案2】:
    1. 与重构相比,某些文档的改进更大。
    2. 您的 -&gt; 宏会混淆 sbcl 的类型推断。您应该将(-&gt; x) 扩展为x,并将(-&gt; x y...) 扩展为(let (($ x)) (-&gt; y...))
    3. 你应该学会使用loop,并在更多的地方使用它。 dolist 带有额外的突变不是很好
    4. 在很多地方你应该使用destructuring-bind 而不是(rest (rest ))。您也不一致,因为有时您会为此写 (cddr...)
    5. 您的block* 存在许多问题:
      1. 它使用了(let (foo) (setf foo...)),这会导致 sbcl 类型推断出错。
      2. 名称block* 意味着各种绑定的作用域可以引用那些先前定义的东西,但实际上所有初始值都可以引用任何变量或函数名称,如果该变量尚未初始化,则它计算结果为零。
    6. 当函数可以在外部时,在另一个函数内部定义大量函数的风格比 Common Lisp 更典型的方案(它有语法)。
    7. get-x-y-and-z-ranges 确实需要使用loop。我认为这也是错误的:列表的长度不同。
    8. 您需要定义一些访问器函数,而不是使用first 等。甚至可能是一个struct(!)
    9. (sort foo) 可能会破坏 foo。你需要做(setf foo (sort foo))
    10. 基本上没有理由使用do。使用loop
    11. 您可能应该在几个地方使用:key
    12. 你写的是defvar,但我认为你的意思是defparameter
    13. *t* 是个愚蠢的名字
    14. 大多数名字都很糟糕,似乎无法告诉我发生了什么。
    15. 我可能是个白痴,但我完全不知道你的程序在做什么。它可能需要做很多工作

    【讨论】:

    • 丹,感谢您的有用建议。我稍后会更新我的代码并再次链接它。
    • 在第 2 项中,请告诉我 SBCL 手册的源 URL。我知道标识符“->”用于 Racket 中的合同语法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-03
    • 2011-02-04
    • 2012-07-11
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多