如果你打开family.l,你会看到这个:

请注意,数据库关系定义是相同的,只是属性名称要短得多:nminstead of name,painstead offather等等。这主要是编码风格的问题(在我看来,较长的属性看起来更友好)。
较长属性名称的潜在缺点:与基于表格的格式(例如 CSV)不同,属性名称存储在每条记录中,因此如果您确实有大量数据,则可能会出现问题。但不要忘记:未成熟的优化是万恶之源。
定义数据库块大小
在底部,您会看到以下几行:
(dbs (0) # @:64 (2 +Person) # A:256 (3 (+Person nm)) # B:512 (3 (+Person job dat fin)) ) # C:512
nm代表name,dat代表birthday,fin代表death day。
这是什么意思?函数( “dbs数据库大小”)初始化全局变量*DBs。它将一个列表作为参数,其中每个列表元素在其 CAR(块大小因子)中都有一个数字,以及哪些项目存储在 CDR 中的信息。
由 指示的默认块大小0为 64 字节。类似地,1代表 128 Byte、2256 Byte 等等。在我们的示例中,我们看到定义了四个数据库文件。
如果您进入-family文件夹,您会看到有四个文件:@、A和. 如果你尝试用普通的文本编辑器打开它们,你会看到它们是二进制文件,里面只有很少的可读字符串。让我们看看这些来自哪里以及为什么我们有四个文件而不是一个。BC
让我们检查它们的大小,例如$ ls -l:
文件大小@为 320 kB。我们知道一个块是 64 kB,即文件@包含 5 个块。文件B包含 43008 kB/256 kB = 168 个块。
为什么我们要不厌其烦地定义块大小?每条记录都从一个新块开始。如果我们的块大小远小于我们的记录大小,那么我们每条记录需要很多块。更糟糕的是,如果我们的项目小于块大小,我们会放弃很多空白空间。
同样,对于非常小的应用程序,它应该无关紧要,但它可能是可扩展性的一个重要因素。
定义数据库内容
现在我们已经定义了每个数据库文件的块大小,我们需要考虑在哪里存储什么。
您可能还记得,我们将人名 ( nm) 定义为非唯一索引,并将工作、生日和死亡日期 ( job dat fin) 定义为应该可搜索的参考。换句话说,这些属性应该被索引。
让我们检查一下函数的文档dbs:
(dbs . lst)
初始化全局变量*Dbs。中的每个元素在lst其 CAR 中都有一个数字(要存储在 中的数据库文件的块大小比例因子*Dbs)。CDR 元素要么是类(以便该类的对象稍后存储在相应的文件中),要么是具有 CAR 中的类和 CDR 中的关系列表的列表(以便这些关系的索引树进入该文件)。
让我们将其与我们的示例进行比较:
(dbs (0) # @:64 (2 +Person) # A:256 (3 (+Person nm)) # B:512 (3 (+Person job dat fin)) ) # C:512
换句话说,我们的数据库文件@(块大小 64 kB)是空的(除了根对象和其他一般元信息)。第二个文件A(块大小 256 kB)包含 person 对象(及其子类+Woman和+Man)。第三个文件包含名称索引。您可能还记得,我们选择 soundex 算法进行索引,这意味着除了全文索引之外,还保留了语音上相似的变体。在第四个文件中,我们存储工作、生日和死亡日期信息。
在 REPL 中处理多个数据库文件
现在让我们重复上一篇文章中的小实验。我们用我们的文件启动 REPL family.l:
$ pil family.l + :
让我们检查一下全局变量*Dbs:
: *Dbs -> (0 2 3 3)
很好,所以 REPL 已经“知道”数据库的正确块大小。这对于正确读取可用数据很重要。
设置命名空间
在我们打开数据库文件之前,我们需要设置命名空间。命名空间告诉解释器在哪里寻找符号。
在family.l文件的顶部,您可以找到以下行:
(符号'家庭'svg'微微)
此语法对应于symbols函数的“第四种形式”。从文档中:
在第四种形式中,sym1如果它的值被初始化NIL并且没有被修改,则被初始化为一个新的命名空间,并且sym1,sym2并且所有后续参数都被设置为当前命名空间列表。
因此,命名空间名称family已创建,所有新符号现在都可以在family命名空间中找到。
因此,在我们加载库文件之前,我们还应该将 REPL 设置为这个命名空间。为此,我们symbols再次使用该函数,这次使用以下语法设置命名空间symbols lst:
: (symbols '(family svg pico)) -> (pico) family:
可以看到由于family提示符前面的原因,修改成功。现在让我们打开数据库文件。我们可以通过指定文件夹来做到这一点(斜杠/很重要!):
家庭:(池“家庭/”*Dbs) -> T
让我们应用我们在上一篇文章中学到的知识:让我们看看+Men该collect函数的所有条目。
family: (more (collect 'nm'+Man) show) {A64} (+Man) ma {A57} fin 711698 dat 688253 nm "Adalbert Ferdinand Berengar Viktor of Prussia" pa {A55}
<Enter>我们得到更多的条目。如您所见,数据库中预先填充了皇室成员。
我们找到的第一个条目是“普鲁士的 Adalbert Ferdinand Berengar Viktor”,符号名称是{A64}。数字是八进制数中条目的块位置:八进制 64 是十进制 52,这意味着该记录从数据库文件 A 中的块 52 开始。
玩弄
如前所述,collect提供了一些有助于搜索和过滤结果的选项。现在让我们尝试查找出生于 1982 年 1 月 1 日至 1988 年 12 月 31 日之间的 Persons 的所有记录。
family: (collect 'dat'+Person (date 1982 1 1) (date 1988 12 31)) -> ({A30} {A27} {A20})
我们正好找到三个条目。要查看它们的名称,我们可以向collect函数添加另一个参数:
家庭:(收集'dat'+人(日期1982 1 1)(日期1988 12 31)'nm) ->(“威廉”“亨利”“比阿特丽斯”)
要在数据库中查找单个对象,请db使用以下函数:
家庭:(db'nm'+人“爱德华”) -> {A13}
您可能还记得,我们将名称设置为非唯一索引。因此,名称为“Edward”的条目可能不止一个。让我们用进一步的数据来指定它:
家庭:(db'nm'+Person“Edward”'job“Prince”'dat(日期 1964 3 10)) -> {A13}
显然,没有接口的数据库有点没用。让我们回到 Web 应用程序教程,看看如何将数据库集成到我们的 GUI 中。


还没有评论,来说两句吧...