Я хочу определить макрос LISP, такой как dolist
, который позволяет мне определять необязательный выходной аргумент. В следующем примере этот макрос будет называться doread
. Он будет читать строки из файла и возвращать количество найденных строк таким образом.
(let ((lines 0))
(doread (line file lines)
;; do something with line
(incf lines)))
Проблема в том, что lines
работает в приведенном выше макросе
Я могу делать то, что хочу, с & ключом, но не с & необязательным & ключом (и ключ & необходим, так как я хочу контролировать, как читается файл; например, с read
или read-line
или любым другим).
Теперь следующее работает НО , чтобы работать неправильно. Здесь аргумент out
должен быть &key
, а не & необязательным:
;; this way works...
(defmacro doread ((it f &key out (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)))
;; lets me define something that reads first line of a file
(defun para1 (f)
"Read everything up to first blank line."
(with-output-to-string (s)
(doread (x f :take #'read-line)
(if (equalp "" (string-trim '(#\Space #\Tab) x))
(return)
(format s "~a~%" x)))))
(print (para1 sometime)) ; ==> shows all up to first blank line
Я хотел бы сделать следующее: обратите внимание, что out
теперь переместился в &optional
:
(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)))))
но это я использую &optional out
я получаю
loading /Users/timm/gits/timm/lisp/src/lib/macros.lisp
*** - GETF: the property list (#'READ-LINE) has an odd length