我想解析Wavefront OBJ file中的文本行。目前我只對「V」和「F」類型感興趣。 我的算法如下:如何讓這段代碼更簡單,更清晰,更「寧靜」?
- 檢查,如果行不爲零(否則第2步會失敗)「#」
- 下降後評論和內飾空間
- 下降前綴「V」或「F」
- 將字符串拆分爲元素列表,其中每個元素
- 如果它是像符號一樣被分割爲列表| 34/76/23 |
- 已從列表轉換:我只接受一個元素,第一個默認爲
- 或強制爲給定類型(如果它已經是原子序號)。
下面是代碼:
(defun parse-line (line prefix &key (type 'single-float))
(declare (optimize (debug 3)))
(labels ((rfs (what)
(read-from-string (concatenate 'string "(" what ")")))
(unpack (str &key (char #\/) (n 0))
(let ((*readtable* (copy-readtable)))
(when char ;; we make the given char a delimiter (space)
(set-syntax-from-char char #\Space))
(typecase str
;; string -> list of possibly symbols.
;; all elements are preserved by (map). nil's are dropped
(string (delete-if #'null
(map 'list
#'unpack
(rfs str))))
;; symbol -> list of values
(symbol (unpack (rfs (symbol-name str))))
;; list -> value (only the requested one)
(list (unpack (nth n str)))
;; value -> just coerce to type
(number (coerce str type))))))
(and line
(setf line (string-trim '(#\Space #\Tab)
(subseq line 0 (position #\# line))))
(< (length prefix) (length line))
(string= line prefix :end1 (length prefix) :end2 (length prefix))
(setf line (subseq line (length prefix)))
(let ((value (unpack line :char nil)))
(case (length value)
(3 value)
(4 (values (subseq value 0 3) ;; split quad 0-1-2-3 on tri 0-1-2 + tri 0-2-3
(list (nth 0 value)
(nth 2 value)
(nth 3 value)))))))))
第四步(標籤 「解壓縮」)是一種遞歸的。這是一個功能,可以自己調用三次。
無論如何,這個解決方案似乎很笨拙。
我的問題是:如何用更短,更清晰的代碼解決這個任務?
如何使代碼更lispy?當然,還有更多的括號。此外,全球搜索和替換的''''' – 2011-01-26 07:04:02