Works for me:
(defmacro doread ((it f &optional out &key (take #'read)) &body body) "Iterator for running over files or strings." (let ((str (gensym))) `(with-open-file (,str ,f) (loop for ,it = (funcall ,take ,str nil) while ,it do (progn ,@body)) ,out))) (defun para1 (f) "Print everything up to first blank line. Return the lines found in that way" (let ((lines 0)) (doread (x f lines :take #'read-line) (if (equalp "" (string-trim '(#\Space #\Tab) x)) (return) (and (incf lines) (format t "~a~%" x)))))) Using it in LispWorks:
CL-USER 104 > (para1 (capi:prompt-for-file "text file")) ;;; -*- mode: Lisp; Base: 10 ; Syntax: ANSI-Common-Lisp ; buffer-read-only: t; -*- ;;; This is ASDF 3.3.3: Another System Definition Facility. ;;; ;;; Feedback, bug reports, and patches are all welcome: ;;; please mail to <[email protected]>. ;;; Note first that the canonical source for ASDF is presently ;;; <URL:http://common-lisp.net/project/asdf/>. ;;; ;;; If you obtained this copy from anywhere else, and you experience ;;; trouble using it, or find bugs, you may want to check at the ;;; location above for a more recent version (and for documentation ;;; and test files, if your copy came without them) before reporting ;;; bugs. There are usually two "supported" revisions - the git master ;;; branch is the latest development version, whereas the git release ;;; branch may be slightly older but is considered `stable' 15 It's just that once you want to specify :take you also need to provide the optional arg. That's a common pitfall and that's why the combination of optional and keyword args is not liked.