我需要从数据库中读取一个通用Lisp对象的字符串。对象应该是一个包含两个双浮动元素的列表;“(1.0d02.0d0)”,例如:
(let* ((str "(1d0 2d0)")
       (off (read-from-string str)))
  (destructuring-bind (x y)
      off (list x y)))但是,是否存在字符串格式不正确的情况?例如,查询失败,或者对象不存在。代码将给出arg计数错误:
error while parsing arguments to DESTRUCTURING-BIND:
  too few elements in
    ()
  to satisfy lambda list
    (X Y):
  exactly 2 expected, but got 0
   [Condition of type SB-KERNEL::ARG-COUNT-ERROR]我必须使用以下代码来进行类型检查。
(let* ((str "(1d0 2d0)")
       (off (read-from-string str)))
  (destructuring-bind (x y)
      (if (and off
               (typep off 'list)
               (= 2 (length off)))
          off
          (list 0d0 0d0)) (list x y)))如果str没有正确格式化,代码段将返回默认值。:(0.0d0.0d0);
我做得对吗?有更好的方法来避免这个错误吗?
发布于 2016-12-15 12:20:35
请注意,有许多可能的错误来源。例如,读者可以检测错误。
确保处理错误:
(defun get-it (s)
  (let ((*read-eval* nil))      ; don't execute code on reading!
    (flet ((check (it)
             (if (and (listp it)
                      (= (length it) 2)
                      (every #'double-float-p it))
                 it
               (error "data is not a list of two double-floats: ~a" it))))
             (handler-case (check (read-from-string s))
               (error (condition)
                 (princ condition)
                 (list 0.0d0 0.0d0))))))
CL-USER 34 > (get-it "(0.0d0 0.0d0)")
(0.0D0 0.0D0)
CL-USER 35 > (get-it "(0.0d0 0.0d0")
End of file while reading stream #<SYSTEM::STRING-INPUT-STREAM 40E06AD7DB>.
(0.0D0 0.0D0)
CL-USER 36 > (get-it "(0.0d0 foo:aa))")
Reader cannot find package FOO.
(0.0D0 0.0D0)
CL-USER 37 > (get-it ")")
Unmatched right parenthesis.
(0.0D0 0.0D0)
CL-USER 38 > (get-it "(1 2 3)")
data not a list of two double-floats: (1 2 3)
(0.0D0 0.0D0)https://stackoverflow.com/questions/41156543
复制相似问题