При программировании на Прологе я часто пишу предикаты, поведение которых должно быть полудетерминированным при вызове со всеми экземплярами аргументов (и чье поведение должно быть недетерминированным в противном случае).
Конкретным вариантом использования этого является мой предикат walk/3
, который реализует обход графа. Поскольку между двумя вершинами может существовать несколько путей, реализация (+,+)
дает несколько точек выбора после true
. Однако они совершенно бесполезны. Вызывающий код должен явно использовать once/1
по соображениям производительности.
%! walk(+Graph:ugraph, +StartVertex, +EndVertex) is semidet.
%! walk(+Graph:ugraph, -StartVertex, +EndVertex) is nondet.
%! walk(+Graph:ugraph, +StartVertex, -EndVertex) is nondet.
%! walk(+Graph:ugraph, -StartVertex, -EndVertex) is nondet.
Полудетерминизм может быть вызван использованием once/1
в вызывающем контексте, но я хочу реализовать полудетерминизм как свойство предиката walk/3
, а не как нечто, что требует особого обращения при каждом его вызове.
Помимо заботы об эстетике кода, контекст вызова не всегда должен знать, является ли его вызов walk/3
полудетерминированным или нет. Например:
%! cycle(+Graph:ugraph, +Vertex) is semidet.
%! cycle(+Graph:ugraph, -Vertex) is nondet.
cycle(Graph, Vertex):-
walk(Graph, Vertex, Vertex).
Я придумал следующее решение, которое действительно дает правильное поведение.
walk_wrapper(Graph, Start, End):-
call_ground_as_semidet(walk(Graph, Start, End)).
:- meta_predicate(call_ground_as_semidet(0)).
call_ground_as_semidet(Goal):-
ground(Goal), !,
Goal, !.
call_ground_as_semidet(Goal):-
Goal.
Однако у этого решения есть недостатки:
- Это недостаточно общее, например иногда
ground
должно бытьnonvar
. - Это не стилистический, требующий дополнительной оболочки предиката каждый раз, когда он используется.
- Это также может быть немного неэффективным.
Мой вопрос: есть ли другие способы, которыми часто встречающиеся паттерны (нед) детерминизма, подобные описанному здесь, могут быть в целом / эффективно / стилистически запрограммированы в Прологе?
memberchk/2
, когда первый аргумент является заземленным, и какmember/2
, когда первый аргумент не заземлен? - person   schedule 04.08.2014memberchk/2
, ниmember/2
не являются ISO. Но, по крайней мере,member/2
является частью Пролога пролог. - person false   schedule 04.08.2014memberchk(a,Xs),Xs=[b,a].
терпит неудачу, ноmemberchk(a,Xs),Xs=[b,a].
успешно. - person false   schedule 04.08.2014memberchk(X, L) :- member(X, L), !.
- person CapelliC   schedule 04.08.2014member/2
иmemberchk/2
, поскольку это могло сбивать с толку. (Кроме того, я ошибался насчет ISO-статуса предикатов, поэтому спасибо, что указали на это!) - person Wouter Beek   schedule 04.08.2014memberchk(a,Xs),Xs=[b,a].
vs.Xs=[b,a], memberchk(a,Xs).
? - person mat   schedule 04.08.2014