我最近对 Prolog 以及如何使用它来表示和查询比我随处可见的常见父/子示例更真实的数据集感到好奇。
为了玩玩,我生成了一个具有以下结构的小数据集:
books:
- titles:
- My first book
- My first attempt at a book
authors:
- firstname: Alice
lastname: Ecila
- firstname: Bob
lastname: Obb
经过几次尝试,我最终得到了这样的东西:
book(1).
title(book(1), "My first book").
title(book(1), "My first attempt at a book").
author(book(1)).
firstname(author(book(1)), "Alice").
firstname(author(book(1)), "Bob").
lastname(author(book(1)), "Ecila").
lastname(author(book(1)), "Obb").
这对于查询有关书籍的信息非常有效,但我完全失去了嵌套对象属性之间的关系。例如,没有办法知道
lastname
的 Alice
。另一方面,如果我尝试将书籍表示为这样的单个术语:
book(
title("My first book"),
author(
firstname("Alice"),
lastname("Ecila")
)
).
book(
title("My first book"),
author(
firstname("Bob"),
lastname("Obb")
)
).
book(
title("My first attempt at a book"),
author(
firstname("Alice"),
lastname("Ecila")
)
).
book(
title("My first attempt at a book"),
author(
firstname("Bob"),
lastname("Obb")
)
).
或者这个:
book(
[ title("My first book"),
title("My first attempt at a book")
],
[ author(
firstname("Alice"),
lastname("Ecila")
),
author(
firstname("Bob"),
lastname("Obb")
)
]
).
我要么丢失了一定数量的信息,要么变得太复杂而无法查询。树似乎很简单,可以表示,但一般来说,图形似乎更复杂。
所以这是我的问题:在序言中表示复杂的嵌套对象的首选方法是什么?
我也在寻找关于这个特定主题的样本和/或文献。
只需将它们放在桌子上即可。例如:
book(1).
book_title(1, 'My first book').
book_title(1, 'My first attempt at a book').
book_author(1, 'Alice', 'Ecila').
book_author(1, 'Bob', 'Obb').
book_titles(B, Ts) :-
bagof(title(T), book_title(B, T), Ts).
book_authors(B, As) :-
bagof(author(firstname(X), lastname(Y)), book_author(B, X, Y), As).
book_titles_authors(B, book(B, Ts, As)) :-
book_titles(B, Ts),
book_authors(B, As).
如您所见,您实际上可以在 Prolog 中编写查询。我这样做只是为了表明一旦您拥有关系数据,就可以很容易地查询它并将它们放在一起,如果您愿意,可以嵌套。
?- book_titles_authors(1, Book).
Book = book(1,
[title('My first attempt at a book'),
title('My first book')
],
[author(firstname('Alice'),
lastname('Ecila')),
author(firstname('Bob'),
lastname('Obb'))
]).
这里是典型的 RDBMS 和 vanilla Prolog 之间的一些区别:
请记住这是普通的 Prolog。由于 Prolog 是一种高级通用编程语言,您可以通过一些努力来实现其中的任何一种。一些功能已经作为库存在。
Prolog 作为一种查询语言的一个巨大优势是它的组合非常好,这与 SQL 不同。