1
\$\begingroup\$

I have been meaning to learn LISP and for a small task I wanted to find out the sum of all integers on STDIN. So for

> clisp a.lisp
1
2
3^D
6

My code is as follows. I have a small helper function, my core function and the invocation of it.

(defun read-int()
  (parse-integer (read-line)))

(defun sum-stdin()
    (handler-case
      ; recurse
      (+ (read-int) (sum-stdin))
      ; base case: if eof
      (error(c)
        (values 0))))

(write (sum-stdin))

Is this according to "the lisp way"?

One thing I see is that it feels weird to basically have the base case of my recursive function what would otherwise be the catch block in a non-functional language. I don't think there is a rule against it, but it just seems very unusual and hacky.

\$\endgroup\$
2
\$\begingroup\$

Dealing with end of file in I/O operations:

There are two basic ways to deal with EOF in functions like read-line:

1) Return a value

           ; stream     ; signal eof error     ; return value if EOF
(read-line stream       nil                    nil)

2) Signal an error

           ; stream     ; signal eof error
(read-line stream       t)

Typical way:

  • use a loop, like SDS said
  • don't signal an error, but deal with an explicit EOF value

Less typical:

  • use a loop, like SDS said
  • signal an error and handle it -> might need slightly more tricky error handling code

Possible:

  • use a loop, like SDS said
  • hide the error handling code behind a macro...
\$\endgroup\$
3
\$\begingroup\$

No, this is not lispy at all.

Lispers use recursion only when necessary, not as a generic substitute for iteration. Moreover, even in scheme they use tail recursion instead of iteration, and your code is not tail recursive.

A typical lisp solution would be

(defun sum-stream(&optional (s *standard-input*))
  (loop for line = (read-line s nil nil) while line
      sum (parse-integer line)))
(print (sum-stream))
\$\endgroup\$
  • \$\begingroup\$ I would really liked to have given this the answer checkmark -- because it shows the better solution. But the other answer starts to explain the proper way, so it seems more "complete" \$\endgroup\$ – user45891 Jun 27 at 22:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.