Пролог ярлык для создания собственного перечисления - PullRequest
3 голосов
/ 14 января 2010

Я пытаюсь создать собственное перечисление с помощью ряда фактов.

greater(X,Y) :- less (Y,X).

less(a,b).
less(b,c).
less(c,d).

Это прекрасно работает, однако есть значительные повторения.

Я пытаюсь сократить это. Есть ли способ использовать массив для простой линейной серии фактов с помощью преобразования?

transform([a,b,c,d])

resulting in the same less definitions.

Я уже создал определение "less", которое использует массив и функцию nextto / member для тестирования, однако я не могу добавить исключения или эквивалентные случаи, как я мог бы с отдельными объявлениями. Отсюда мой интерес к сокращению простого определения случая, а затем желание дополнить его дополнительными определениями.

Это напоминает мне, где defmacro в lisp полезен.

Спасибо.

Edit:

Мне удалось создать одну серию, используя assert. Он все успешно определяет, но возвращает ошибку. У меня сложилось впечатление, что это неправильный метод.

set_less([]).
set_less([X,Y|L]):- assert( myless(X,Y) ) , set_less([Y|L]).
:- set_less([a,b,c,d]).

Output: 
Goal (directive) failed: user:set_less([a, b, c, d])

?- listing.

:- dynamic myless/2.

myless(a, b).
myless(b, c).
myless(c, d).

Второе редактирование:

mylist([a,b,c,d]).

set_less([]).
set_less([_]).  ----- Key!
set_less([X,Y|L]):- assert( myless(X,Y) ) , set_less([Y|L]).
:- set_less([a,b,c,d]).

Это работает! Это хороший способ определения пользовательских перечислений? Я вижу, это работает сейчас, спасибо!

Ответы [ 3 ]

2 голосов
/ 17 января 2010
term_expansion(list_enumerate(Name,List), [mylist(Name,List)|Flist]) :-
    list_enumerate_to_list(List, Flist).

list_enumerate_to_list([], []).
list_enumerate_to_list([_], []).
list_enumerate_to_list([X,Y|Xs], [myless(X,Y)|Ys]) :-
        list_enumerate_to_list([Y|Xs], Ys).

list_enumerate(test,[a1,b1,c1,d1]).
list_enumerate(first,[a,b,c,d]).
list_enumerate(second,[f,e,g,h]).

testless(X,Y) :- myless(X,Y).
testless(X,Y) :- myless(X,Z) , testless(Z,Y).

Output---------------------------------------------------------------

?- listing.


myless(a1, b1).
myless(b1, c1).
myless(c1, d1).
myless(a, b).
myless(b, c).
myless(c, d).
myless(f, e).
myless(e, g).
myless(g, h).

?- testless(a1,c1).
true ;
false.

?- testless(X,c1).
X = b1 ;
X = a1 ;
false.

Это работает! Спасибо супругу на #prolog на freenode.

При запуске есть несколько предупреждений, но их можно игнорировать.

1 голос
/ 18 января 2010

Если вам нужен полный порядок ваших товаров, вы можете просто сопоставить их с натуральными числами во время консультации / компиляции. При сравнении, просто посмотрите на цифры и сравните их. Это должно быть намного быстрее, если у вас много предметов.

Примерно так:

% Key generation
make_keys(List, Keys) :-
    make_keys(List, 0, Keys).

make_keys([], _, []).
make_keys([El | Els], Index, [mykey(El, Index) | Ks]) :-
    NewIndex is Index + 1,
    make_keys(Els, NewIndex, Ks).

% Mapping ordering/1 to a set of mykey/2
term_expansion(ordering(List), Clauses) :-
    make_keys(List, Clauses).

% Ordering
ordering([first, second, third, fourth, fifth]).

% Comparison by looking at the keys
greater_than(X, Y) :-
    mykey(X, XK),
    mykey(Y, YK),
    XK > YK.
1 голос
/ 14 января 2010

Я уже создал определение "less", в котором для проверки используются массив и функция nextto / member, однако я не могу добавлять исключения или эквивалентные случаи, как я мог бы с отдельными объявлениями.

Вы все еще можете добавить свои "исключения и эквивалентные случаи" перед своим "определением массива", точно так же, как вы добавили бы их перед рядом фактов, не так ли?

Или, может быть, вы хотите поэкспериментировать с Univ, оператором = .. .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...