I need to read a string of Common Lisp object from database. The object should be a list with two elements of double-float; "(1.0d0 2.0d0)" for example:
(let* ((str "(1d0 2d0)")
(off (read-from-string str)))
(destructuring-bind (x y)
off (list x y)))
But there are conditions that the string is not properly formatted? For example, the query failed, or the object doesn't exist. The code will give arg-count-error:
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]
I have to use the following code to do type-check.
(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)))
The code snippet will return the default value if the str is not properly formatted. : (0.0d0 0.0d0);
Am I doing it right? Is there an better way to avoid this error?
There are a few ways to go about this. One option would be to use a pattern matching library (such as Trivia).
If you want to check that
X
andY
are floats, you can add a guard patternAs pointed out by Rainer Joswig in his answer,
READ-FROM-STRING
can cause other errors and*READ-EVAL*
should be set toNIL
when reading.Also remember that you can use lambda list keywords, such as
&OPTIONAL
, withDESTRUCTURING-BIND
. Using Alexandria for theENSURE-LIST
-function, you could writeIf you don't want to use any libraries, you can just check that a list is given yourself