Common Lisp:如何在读取功能中选择符号所属的包

问题描述

这似乎是一个非常简单的问题,但是我仍然是普通Lisp的初学者。 我尝试加载如下文件。不带包装的符号'year 'month等可以在每个文件中进行比较。

;;; file db.lisp
((year 2010
    (month 5
        (1 100 "A")
        (2  -5 "B"))
    (balance 10)
    (month 6
        (1  -7 "C")
        (2  -8 "D")))
(load-from-csv-format-1 "db2011.csv")
(load-from-csv-format-2 "db2012.csv"))

我设法将现有的Lisp代码转换如下

(defpackage :db
    (:use :common-lisp :db.csv-format-1))
(in-package :db)

(defun read-db ()
  (let ((db (with-open-file (stream "db.lisp")
             (read stream))))
...
(case (car x)
    (year (expand-year x))
    (load-from-csv-format-1 (load-format-csv-format-1-impl (second x)))
    (load-from-csv-format-2 (load-format-csv-format-1-impl (second x)))
...

现在,所有符号都属于软件包:db。这对我来说有一个缺点,因为 对read-db的所有调用都必须在:db内部进行。如果我现在想分开 所有不同csv格式的不同软件包中的内容都不再起作用,因为 例如以下'balance属于db.csv-format-1软件包,无法比较 与db::balance符号相对应。

(defpackage :db.csv-format-1
    (:use :common-lisp)
    (:export :load-from-csv-format-1-impl))
(in-package :db.csv.format-1)
(defun load-format-csv-format-1-impl (path)
    (list 'balance 20))

所以我的问题是,如何在Lisp中正确完成此操作?可以指定以某种方式阅读, 在哪个包中创建符号,然后在此之外以某种方式访问​​这些符号 包装?

解决方法

read intern读取的内容 包装*package*,以便您可以 做到这一点:

(defun read-db ()
  (let* ((*package* (find-package #:db))
        ((db (with-open-file (stream "db.lisp")
               (read stream)))))
   ...))

PS 。作为初学者,您可能喜欢阅读Resources for learning Lisp中推荐的一些书籍。