开发者

Lisp: Help NOT returning a value?

开发者 https://www.devze.com 2023-02-20 04:30 出处:网络
I have written a function which accepts a list of strings, and prints them line-by-line. (defun print-to-lines (slist)

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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号