我写了一个prolog项目,现在我必须将其更改为Logtalk文件。在代码中,我可以使用代码将新事实断言到另一个 prolog 文件:
:- dynamic(student/5).
:- use_module(library(persistency)).
:- persistent(student(id, name, surname, mark, studies)).
:- initialization(db_attach('student_database.pl', [])).
add_student(ID, Name, Surname, Mark, Studies):-
with_mutex(student_db, assert_student(ID, Name, Surname, Mark, Studies)).
现在我想在 Logtalk 中做一些类似的东西,但不是事实,而是对象。Ofc 我知道如何制作新对象(通过协议create_object/4
),但我不知道如何将其作为数据库保存在文件中。
该协议如下所示:
:- protocol(student).
:- public([
id/1,
name/1,
surname/1,
studies/1,
marks/1
]).
:- end_protocol.
谁能帮我保存这些对象?
序列化动态对象通常可能很复杂,具体取决于对象的依赖关系,但您的情况似乎更简单,因为每个对象仅依赖于单个协议并且仅包含事实。
当使用支持保存状态的后端Prolog系统(例如SICStus Prolog,SWI-Prolog或YAP)时,一个简单的解决方案是创建一个保存的状态。由于保存状态没有标准,因此此解决方案必然是不可移植的。
当无法保存状态或寻求可移植解决方案时,我们需要为保存的数据定义一种格式,以便我们可以在加载和恢复对象时对其进行解释。假设我们要将对象恢复为动态对象(因为它们最初是使用create_object/4
谓词创建的),并使用一个简单的表示形式data/1
来表示保存的状态。我们可以定义一个通用serializer
对象如下(未经测试):
:- object(serializer).
:- public([
save/2,
restore/1
]).
save(Protocol, File) :-
protocol_property(Protocol, public(Predicates)),
open(File, write, Stream),
write_canonical(Stream, protocol(Protocol)), write(Stream, '.n'),
forall(
conforms_to_protocol(Object, Protocol),
save_object(Object, Predicates, Stream)
),
close(Stream).
save_object(Object, Predicates, Stream) :-
object_data(Predicates, Object, [], Data),
write_canonical(Stream, data(Data)), write(Stream, '.n').
object_data([], _, Data, Data).
object_data([Functor/Arity| Predicates], Object, Data0, Data) :-
functor(Fact, Functor, Arity),
findall(Fact, Object::Fact, Data1, Data0),
object_data(Predicates, Object, Data1, Data).
restore(File) :-
open(File, read, Stream),
read_term(Stream, Term, []),
restore_object(Term, _, Stream),
close(Stream).
restore_object(end_of_file, _, _).
restore_object(protocol(Protocol), Protocol, Stream) :-
read_term(Stream, Term, []),
restore_object(Term, Protocol, Stream).
restore_object(data(Data), Protocol, Stream) :-
create_object(_, [implements(Protocol)], [], Data),
read_term(Stream, Term, []),
restore_object(Term, Protocol, Stream).
:- end_object.
然而,这只是一个起点。它可以通过多种方式进行改进,但这主要需要有关特定序列化方案的更多详细信息。
更新
根据上面的代码在 Logtalk git 版本中添加了serialization
示例:https://github.com/LogtalkDotOrg/logtalk3/tree/master/examples/serialization