ruricolist / serapeum

Utilities beyond Alexandria
MIT License
415 stars 41 forks source link

Proposal: read-from-stream #130

Open Ambrevar opened 2 years ago

Ambrevar commented 2 years ago

I found myself using this 3-liner over and over again:

(defun read-from-stream (stream)
  "Return a list of all s-expressions read in STREAM."
  (loop :for value := (read stream nil stream)
        :until (eq value stream)
        :collect value))

Considering the standard already has read-from-string, it's only logical to have the STREAM counterpart. With the small difference that it loops over all s-exps and returns the list of them.

Wanna add it to Serapeum?

Ambrevar commented 2 years ago

Actually I realized that uiop has uiop:slurp-stream-forms and uiop:safe-read-from-string.

So here are the missing parts:

(defun safe-read (&optional
                    (input-stream *standard-input*)
                    (eof-error-p t)
                    (eof-value nil)
                    (recursive-p nil))
  "Like `read' with standard IO syntax but does not accept reader macros ('#.').
UIOP has `uiop:safe-read-from-string' but no `read' equivalent.
This is useful if you do not trust the input."
  (let ((package *package*))
    (uiop:with-safe-io-syntax (:package package)
      (read input-stream eof-error-p eof-value recursive-p))))

(defun safe-slurp-stream-forms (stream)
  "Like `uiop:slurp-stream-forms' but wrapped in `uiop:with-safe-io-syntax' and
package set to current package."
  (uiop:with-safe-io-syntax (:package *package*)
    (uiop:slurp-stream-forms stream)))

But maybe it'd be better to add it to UIOP directly?