I have a Lisp program that's going through nested list and deleting elements that match the element passed through to the function. My issue is, if everything in one of the nested list is deleted, I need to print out () instead of NIL.
(defun del (x l &optional l0)
(cond ((null l) (reverse l0))
((if (atom x) (eq x (car l)) (remove (car l) x)) (del x (cdr l) l0))
(T (del x (cdr l) (cons (if (not (atom (car l)))
(del x (car l))
(car l))
l0)))))
(defun _delete(a l)
(format t "~a~%" (del a l)))
(_delete 'nest '(nest (second nest level) (third (nest) level)))
This returns
((SECOND LEVEL (THIRD NIL LEVEL))
And I need
((SECOND LEVEL (THIRD () LEVEL))
I've tried using the ~:S format but that apparently doesn't work with composite structures. I've also tried the substitute function to replace NIL, also with no results.
Two possible solutions:
I. You can use the format directives ~:A
or ~:S
(format t "~:a" '()) => ()
However, this directive works only on the top level elements of a list, i.e.
(format t "~:a" '(a b () c))
will not print (A B () C)
but (A B NIL C)
So you need to loop through the list applying the ~:A
to each element recursively if it is a cons.
(defun print-parentheses (l)
(cond ((consp l) (format t "(")
(do ((x l (cdr x)))
((null x) (format t ")" ))
(print-parentheses (car x))
(when (cdr x) (format t " "))))
(t (format t "~:a" l)) ))
(print-parentheses '(a b (c () d))) => (A B (C () D))
II. Create a print-dispatch function for empty lists and add it to the pretty print dispatch table:
(defun print-null (stream obj)
(format stream "()") )
(set-pprint-dispatch 'null #'print-null)
(print '(a () b)) => (A () B)
The latter is simpler, but it affects all the environment, which might not be what you want.
We can write an :around
method for print-object
, for the case when the object to be printed is NIL
.
(defvar *PRINT-NIL-AS-PARENS* nil
"When T, NIL will print as ().")
(defmethod print-object :around ((object (eql nil)) stream)
(if *print-nil-as-parens*
(write-string "()" stream)
(call-next-method)))
(defun write-with-nil-as-parens (list)
(let ((*print-nil-as-parens* t))
(write list)))
Example:
CL-USER 73 > (write-with-nil-as-parens '(a b c nil (()) (nil)))
(A B C () (()) (())) ; <- printed
(A B C NIL (NIL) (NIL)) ; <- return value
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With