2012-09-05 208 views
1

如果我在数据库中有一个简单的谓词,是否有一种方法可以请求以特定顺序(asc/desc)返回结果,而无需将它们全部读入内存并执行排序/ 2或做一组/ 3?默认Prolog谓词排序

例如,考虑这个数据库:

animal(dog). 
animal(cat). 
animal(elephant). 
animal(bird). 
animal(aardvark). 

我想以某种方式申报的动物作为其第一项排序ASC,这样我可以简单的查询就喜欢:

?- animal(X). 
X = aardvark ; 
X = bird ; 
X = cat ; 
X = dog ; 
X = elephant ; 
No. 

如果能够这样做对于更像传统数据库来处理我的知识库非常方便。

回答

2

不,你不能对它们进行排序,如果你没有阅读它们。

OFC你可以写谓词排序或生成它们进行排序:

findall(sorted_animal(X),animal(X),Animals), 
sort(Animals,SAnimals), 
maplist(assertz(X),SAnimals), 
compile_predicates([sorted_animal]/1). 

findall(animal(X),animal(X),Animals), 
sort(Animals, SAnimals), 
retractall(animal(X)), 
maplist(assertz(X),SAnimals), 
compile_predicates([sorted_animal]/1). 

,但你必须声明谓词animal/1动态:

:-dynamic(animal/1). 
animal(dog). 
.... 

(在代码文件中)

我用compile_predicates/1来提高速度;但是,这意味着您不能在该谓词上再次使用assert/1retract/1,因此如果您添加/删除动物,请跳过它。

或者您可以使用ordered sets它作为参数传递

1

序言掩盖了复杂的排序问题,注定了数据库访问,FIFO或后进先出法,用默认FIFO严格的时间模型。这是合理的,因为这样的访问定义了的计算模型。

所以没有标准的方法来改变子句检索顺序。

我认为goal_expansion/2可以用来引入这样的功能,我会尝试一个原型。但我不知道我会得到什么有用....

编辑

第一次尝试,但是使用慢(但更简单)缩回/断言。

/* File: order_by.pl 
    Author: Carlo,,, 
    Created: Sep 5 2012 
    Purpose: sort fact 
*/ 
:- module(order_by, 
     [order_by/2 
     ]). 

order_by(PredicateIndicator, Argument) :- 
    ( PredicateIndicator = Module:Functor/Arity 
    ; PredicateIndicator = Functor/Arity, Module = user 
    ), 
    length(EmptyArgs, Arity), 
    P =.. [Functor|EmptyArgs], 
    findall(P, retract(Module:P), L), 
    predsort(by_arg(Argument), L, S), 
    maplist(assert_in_module(Module), S). 

assert_in_module(Module, P) :- 
    assertz(Module:P). 

by_arg(Argument, Delta, E1, E2) :- 
    arg(Argument, E1, A1), 
    arg(Argument, E2, A2), 
    ( A1 @< A2 
    -> Delta = < 
    ; Delta = > 
    ). 

测试文件(我测试只是在用户模块),注意: - 动态声明是必需的:

/* File: order_by_test.pl 
    Author: Carlo,,, 
    Created: Sep 5 2012 
    Purpose: 
*/ 
:- [order_by]. 
:- dynamic animal/1. 

animal(dog). 
animal(cat). 
animal(elephant). 
animal(bird). 
animal(aardvark). 

test :- 
    order_by(animal/1, 1), 
    forall(animal(X), writeln(X)). 

测试结果:

?- test. 
aardvark 
bird 
cat 
dog 
elephant