【发布时间】:2019-06-26 15:42:10
【问题描述】:
我想定义一个像 dolist 这样的 LISP 宏,它可以让我定义一个可选的输出参数。在以下案例研究中,此宏将称为doread。它将从文件中读取行并返回以这种方式找到的行数。
(let ((lines 0))
(doread (line file lines)
;; do something with line
(incf lines)))
问题是让lines 在上述宏中工作
我可以用 &key 做我想做的事,但不能用 &optional &key (并且 &key 是必需的,因为我想控制文件的读取方式;例如使用 read 或 read-line 或其他)。
现在以下工作但以错误的方式工作。这里out 参数必须是&key 而不是&optional:
;; 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
【问题讨论】:
-
请注意,在 DOREAD 中,
f必须是,f。
标签: macros lisp common-lisp