1
\$\begingroup\$

I am calling defvar in the middle of a function definition. And so far I've always seen its use, with defparameter for global variable. Like *error-output* or *standard-output*.

(defun consume-socket-reply (socket end-test-form)
  (do* ((line "" (read-line (usocket:socket-stream socket) nil))
        (text "" (concatenate 'string text line)))
       ((funcall end-test-form) text)))

(defun read-http-content (socket)
  (defvar line)
  (consume-socket-reply socket (lambda () (not line))))

Is there a better way to write what I am trying to do? That is: being able to pass the end-test-form to the final inner loop.

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

Defvar always creates a globally special variable (unless it already exists, of course). It does not matter where you call it.

It is usually used as a toplevel form or directly inside of an eval-when. The only reason to put it anywhere else that I can think of is the use of closures.

In all other cases, I would strongly suspect that the code does not mean what the author thinks it does.

Here, the globally special variable line is created on the first call of read-http-content. This may lead to surprising effects if you use the name line in other places. Don't do that.

\$\endgroup\$
1
\$\begingroup\$

Ok I've modified my code that way, and removed the call to defvar:

(defun consume-socket-reply (socket end-test-form)
  (do* ((line (read-line (usocket:socket-stream socket) nil)
              (read-line (usocket:socket-stream socket) nil))
        (text line (concatenate 'string text line)))
       ((funcall end-test-form line) text)))

(defun read-http-header (socket)
  (consume-socket-reply socket (lambda (line) (equal line ""))))

(defun read-http-content (socket)
  (consume-socket-reply socket (lambda (line) (not line))))
\$\endgroup\$

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.