Common lisp LISP文件I/O-提取和转换信息
我有一个文件(furniture.lisp),基本上是这样的(有更多的条目): 现在,我想要一个函数Common lisp LISP文件I/O-提取和转换信息,common-lisp,Common Lisp,我有一个文件(furniture.lisp),基本上是这样的(有更多的条目): 现在,我想要一个函数(get locations“furniture.lisp”“locations.txt”),它提取三维向量中的对象坐标并将其输出写入文件: (location stove -3.1 -0.9 9) (location drawers-cupboard -3.1 0.1 0) ... 我首先编写一个表达式,逐行读取文件(到目前为止没有参数化): (ql:quickload "split-sequ
(get locations“furniture.lisp”“locations.txt”)
,它提取三维向量中的对象坐标并将其输出写入文件:
(location stove -3.1 -0.9 9)
(location drawers-cupboard -3.1 0.1 0)
...
我首先编写一个表达式,逐行读取文件(到目前为止没有参数化):
(ql:quickload "split-sequence")
(with-open-file (stream "furniture.lisp")
(do ((line (read-line stream nil)
(read-line stream nil)))
((null line))
(princ (split-sequence::split-sequence #\Space line)) ; Just for demonstration
))
但我意识到我没有机会/想法“连接”对象的名称(例如火炉)及其坐标。我需要“(addgv”之后的第二个符号作为名称,变量“单词距离”作为坐标。因此我尝试将文件读入一个大列表:
(defun make-list-from-text (fn)
(with-open-file (stream fn)
(loop for line = (read-line stream nil nil)
while line
collect
(split-sequence::split-sequence #\Space line))))
因此,每一行都是一个子列表(我不知道这个子结构是否是一个优势,也许我应该“展平”结果)。现在我被卡住了。此外,我有一种感觉,我的方法有点不雅观
编辑:
我遵循Svante的方法,最终得到了所需的输出!除了创建一个虚拟包,我还必须为包创建虚拟导出(例如:导出:make-3d-vector
)。此外,:key#car
不起作用,因为我的列表是一个“混合”列表,由子列表组成(例如(make-instance…
)和符号(例如,addgv
)。因此我创建了一个助手函数:
(defun find-helper (list-or-symbol)
(if (listp list-or-symbol)
(car list-or-symbol)
list-or-symbol))
并将
#car
替换为#find-helper
通常的方法是:
(cl-ppcre:regex替换所有“tf:?“content”)
,即替换对包tf
的所有引用,以避免与包相关的错误”()
读取它并分配给变量
不幸的是,这将是一个不可移植的解决方案:
- 处理读卡器错误
- 采取必要措施解决问题
- 继续
它为丢失的包错误调用continue restarts,然后为符号未导出的错误调用continue restarts。重新启动创建包,另一个返回未导出的符号…我的想法是创建一个伪
tf
包,然后读取表单并解析您需要的任何内容。因此像这样的方法(未经测试):
请确保不要忽略将*read eval*
绑定到nil
我不知道addgv
或其他一些函数做什么,但是…如果文件以开头(定义家具(列表
并以额外的结尾),会有帮助吗
?然后您可以一次读取所有文件,然后使用您喜欢的任何方式迭代家具--映射
,dolist
等。这将文件读取问题与如何从每个条目解析出您想要的内容的问题区分开来。在这种情况下,我得到错误:`没有包含nam的包e“TF”(我没有软件包,因为我只需要坐标)。此外,我对实现这一点的一般方法感兴趣(例如,如果源文件有“糟糕的语法”或根本没有与LISP兼容的样式)。
(defun find-helper (list-or-symbol)
(if (listp list-or-symbol)
(car list-or-symbol)
list-or-symbol))
CL-USER 60 > (defun test ()
(handler-bind ((conditions:package-not-found-reader
(lambda (c)
(continue c)))
(conditions:simple-reader-error
(lambda (c)
(continue c))))
(read-from-string "'(foo27:bar19 bar18:foo44)")))
TEST
CL-USER 61 > (test)
(QUOTE (FOO27::BAR19 BAR18::FOO44))
(eval-when (:compile-toplevel :load-toplevel :execute)
(unless (find-package #:tf)
(defpackage #:tf)))
(defun extract-location-file ()
(let ((*read-eval* nil))
(with-open-file (in "furniture.lisp")
(with-open-file (out "locations.txt"
:direction :output
:if-exists :supersede
:if-does-not-exist :create)
(loop :for form := (read in nil)
:while form
:do (print (extract-location form) out)
(terpri)))))
(defun extract-location (form)
`(location ,(third form)
,@(rest (find 'tf::make-3d-vector
(find 'tf::make-pose-stamped
(find 'make-instance
form
:key #'car)
:key #'car)
:key #'car))))