Lisp: Help NOT returning a value?
I have written a function which accepts a list of strings, and prints them line-by-line.
(defun print-to-lines (slist)
(cond
((null slist) slist)
(t (let ((empty (write-line (car slist)))) (print-to-lines (cdr slist))))))
This works great, except there is an extra return value (in this case NIL) at the end of the开发者_如何学编程 output (when run in the debugging window):
CG-USER(16): (print-to-lines '("adam" "emilio" "eoln"))
adam
emilio
eoln
NIL
I understand where that extra NIL comes from (it is the return value of my function), but I want it to not be there. My assignment dictates that this is not present. Is there a way to "fake" it or disable this?
You can use values
without arguments to return no values, i.e. (values)
.
More idiomatic versions of your function could be written with mapc
or dolist
instead of explicit recursion (but you would still need the (values)
because mapc
returns the list and dolist
returns nil
).
I want to dissect and improve your code while providing answers to your questions along the lines.
Standard indentation is two spaces.
(defun print-to-lines (slist)
(cond
((null slist) slist)
(t (let ((empty (write-line (car slist)))) (print-to-lines (cdr slist))))))
You are allowed to make newlines between any two tokens.
(defun print-to-lines (slist)
(cond
((null slist) slist)
(t (let ((empty (write-line (car slist))))
(print-to-lines (cdr slist))))))
The stuff after a condition in a cond
form is evaluated in an
implicit progn
. You do not need to name the value that is thrown
away anyway.
(defun print-to-lines (slist)
(cond
((null slist) slist)
(t (write-line (car slist))
(print-to-lines (cdr slist)))))
In order to return nothing, use values
. Note that this is usually
not necessary, as the return value is not part of the output; it is
just displayed by the REPL (in a syntax highlighting environment,
program output and REPL output are usually different colours). Note
as an aside that values
can also be used to return multiple values.
(defun print-to-lines (slist)
(cond
((null slist) (values))
(t (write-line (car slist))
(print-to-lines (cdr slist)))))
Note that explicit recursion is not needed here. Some other, more concise ideas:
(defun print-to-lines (slist)
(dolist (string slist)
(write-line string)))
(defun print-to-lines (slist)
(mapcar #'write-line slist))
(defun print-to-lines (slist)
(format t "~{~a~%~}" slist))
Maybe this will help:
http://coding.derkeiler.com/Archive/Lisp/comp.lang.lisp/2010-08/msg00553.html
Firstly, in this case, it's not an extra return value. You are printing to *STDOUT*
and the repl is also printing to *STDOUT*
so it just looks like it is. If your function were to print to *FILE*
instead, you wouldn't be having this problem.
your code returns null because of line three
1: (defun print-to-lines (slist)
2: (cond
3: ((null slist) slist)
4: (t (let ((empty (write-line (car slist)))) (print-to-lines (cdr slist))))))
In the case of slist being null you are returning slist hence the nul return value. You could rewrite the function so that rather than returning the null slist it returns another value ( say a function call to write-line or some such).
Additionally look into the format function.
I would restructure this slightly so that you check for the null list earlier in the list search rather than letting the list go empty. For example:
(defun print-to-lines (slist)
(cond
((null (cdr slist)) (write-line (car slist)))
(t (let ((empty (write-line (car slist)))) (print-to-lines (cdr slist))))))
Here's a link to it running: http://ideone.com/tzZrm
Hope this helps,
Jason
精彩评论