我正在尝试验证(在 Common Lisp 中)配置文件的行。我已将它们读入列表列表中,格式为 ((lineno parm value &optional freq start end) (...))。 我希望能够验证配置文件的每一行,识别并显示发现的错误,如果发现任何错误,则以 NIL 结果结束该函数。
我有一个工作函数,但看起来很笨重。我也不知道如何从循环语句中传递 NIL 作为函数的最终结果。
这是我的职责...
(defun validate-config-params (config-params)
"Validate the parsed config parameters."
(loop for config-param in config-params
; config-param is the entire config form (lineno parm value [freq [start [end]]])
for param = (cadr config-param)
for line-number = (car config-param)
for error-message = ""
with error-count = 0
do (unless (or (null param) (and (listp param) (every #'atom param)))
(setf error-message (format nil "~A Incorrect format." error-message)))
(unless (symbolp (first param))
(setf error-message (format nil "~A 1st parm not a symbol." error-message)))
(unless (or (null (second param)) (numberp (second param)))
(setf error-message (format nil "~A 2nd parm not a number." error-message)))
(unless (or (null (third param)) (symbolp (third param)))
(setf error-message (format nil "~A 3rd parm not a symbol." error-message)))
(unless (or (null (fourth param)) (numberp (fourth param)))
(setf error-message (format nil "~A 4th parm not a number." error-message)))
(unless (or (null (fifth param)) (numberp (fifth param)))
(setf error-message (format nil "~A 5th parm not a number." error-message)))
(cond ((not (STRING= error-message ""))
(format T "Line ~A: ~A~% ~A~%" line-number param error-message)
(setf error-message "")
(incf error-count)
nil)
(t 'good)))
(unless (> error-count 0)))
对于配置参数...
(defparameter config-params '((1 NIL)
(2 NIL)
(3 (PENSION 1000 FORTNIGHTLY))
(4 (DEEMING-LOW-RATE (/ 0.25 100)))
(5 (DEEMING-HIGH-RATE (/ 2.25 100)))
(6 (DEEMING-LOW-THR 100000))
(7 (INTEREST 7.2 YEARLY))))
...我得到这个结果...
* (validate-config-params config-params)
Line 4: (DEEMING-LOW-RATE (/ 0.25 100))
Incorrect format. 2nd parm not a number.
Line 5: (DEEMING-HIGH-RATE (/ 2.25 100))
Incorrect format. 2nd parm not a number.
NIL
...这正是我所期望的,但它看起来很笨重。如果我将第 4 行和第 5 行设置为普通数字(即 0.25 和 2.25),它会正确验证,但仍返回 NIL。
我该如何清理它?
我会返回验证结果(t 或 nil)和错误。然后,您可以独立决定如何处理错误(例如打印错误)。
一个临时的定义可能是这样的:
(defun validate-config-parameters (config-parameters)
(let ((errors (loop :for (line (param value freq start end)) :in config-parameters
:unless (symbolp param)
:collect (list line 'param param "not a symbol")
:unless (or (null value) (numberp value))
:collect (list line 'value value "not a number")
:unless (or (null freq) (symbolp freq))
:collect (list line 'freq freq "not a symbol")
:unless (or (null start) (numberp start))
:collect (list line 'start start "not a number")
:unless (or (null end) (numberp end))
:collect (list line 'end end "not a number"))))
(values (endp errors)
errors)))