2012-09-05 260 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