具有动态谓词的模块

标签 module prolog swi-prolog prolog-assert prolog-directive-dynamic

这是以下问题的后续问题:Adapting csv reading for multiple tables

如果我定义了以下模块:

:- module(csv_load_mod,[prepare_db/3]).
:- use_module(library(csv)).
:- set_prolog_stack(global, limit(4*10**9)).

prepare_db(File, Column_Key,Relation) :-
   Column_Key_Term =.. [Column_Key,_],
   Relation_Term =.. [Relation,_,_,_],
   retractall(Column_Key_Term),
   retractall(Relation_Term),
   forall(read_row(File, Row), store_row(Row,Column_Key,Relation)).

store_row(Row,Column_Key,Relation) :-
   Column_Key_Test =.. [Column_Key,ColKeys],
   Row =.. [row|Cols],
   (   call(Column_Key_Test)
   ->  Cols = [RowKey|Values],
       maplist(store_relation(Relation,RowKey), ColKeys, Values)
       ;   ( Cols = [_H|T],
             Column_Key_Term =.. [Column_Key,T],
             assertz(Column_Key_Term)
           )
   ).

store_relation(Relation,RowKey, ColKey, Values) :-
    Relation_Term =.. [Relation,RowKey,ColKey,Values],
    assertz(Relation_Term).

read_row(File, Row) :-
    csv_read_file_row(File, Row, []).

然后我就可以从 csv 文件读取表格。

例如:

:? prepare_db('my_table.csv',mt_col_key, mt_relation).

然后,我将得到一个事实 mt_col_key([col1,col2,...,coln]) 和一组事实 mt_relation/3。但这些将是模块本地的并且不会被导出。我需要使用 csv_load_mod:mt_relation/3 等。有没有办法让模块导出动态谓词或调整 prepare_db/3 所以它断言的事实不是本地的还是它们被断言到调用它的模块?

最佳答案

我简化了应用逻辑,以更好地说明有趣的观点。我们需要三样东西:一个模块“驱动程序”,即 test_csv.pl,通用加载程序,即 csv_module_test.pl,以及至少一个文件,即 file.csv

司机:

:- module(test_csv, [test_csv/0]).
:- use_module(csv_module_test).

test_csv :-
    context_module(CM),
    prepare_db(CM, 'file.csv').

加载器:

:- module(csv_module_test, [prepare_db/2]).
:- use_module(library(csv)).

prepare_db(CM, File) :-
    forall(csv_read_file_row(File, Row, []), store_row(CM, Row)).

store_row(CM, Row) :-
    Row =.. [row,RelName|Cols],
    Record =.. [RelName|Cols],
    CM:assertz(Record).

测试数据,文件.csv:

key,desc,col1,col2,col3,col4,col5
key_x,desc_x,1,2,3,4,5
key_y,desc_y,10,20,30,40,50

那么,

?- test_csv.
true.

?- test_csv:listing.

:- dynamic rel/3.


test_csv :-
    context_module(A),
    prepare_db(A, 'file.csv').

:- dynamic key/1.


:- dynamic key_y/6.

key_y(desc_y, 10, 20, 30, 40, 50).

:- dynamic key_x/6.

key_x(desc_x, 1, 2, 3, 4, 5).

:- dynamic key/6.

key(desc, col1, col2, col3, col4, col5).
true.

也就是说,关系已被声明为动态并在驱动程序模块中断言...

注意:关系的名字是假的,因为我一开始试图遵循你的应用逻辑,后来转向简化的方法......

关于具有动态谓词的模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31584614/

相关文章:

ruby - 如何通过包含模块来包装 Ruby 方法的调用?

parsing - 如何将序言分析树转换回逻辑句子

c - 如何使用包含 swi-prolog.h 的 gcc 创建 .dll 文件?

prolog - Prolog-回文函

prolog - 为什么 SWI-Prolog 发明 f/2 只给定 f/1?

prolog - Prolog DCG语法规则中的堆栈溢出:如何有效或延迟地处理大型列表

module - 在解释和编译模式下包含 OCaml 模块

python - 在导入的文件中进行本地导入

javascript - 变量被意外覆盖

list - 有人可以帮忙解释一下这个复制功能的工作原理吗?