编写 Prolog 谓词的一些最佳实践是什么,以便它以指定参数的不同方式工作

问题描述 投票:0回答:1

我正在尝试实现一些简单的谓词,比如 my_length 或 my_append。

如果我们事先知道我们想要找到一个列表的长度,或者我们想要追加两个列表,这对我来说很容易。 (即我知道什么是输入,什么是输出)。

在 Prolog 中,可以用其他方式做事。像 my_length(L, 3) 或 my_append(A,B,[1,2,3])。

有时,我的代码可以工作。有时,它没有。

我发现很难确保它以各种不同的方式工作。除非它只是我自己的辅助谓词,否则您永远不会真正知道您的用户想要用什么来测试它。有时问题甚至可能定义不明确,例如

my_length(L, 5)
输出什么是不清楚的。

有什么最佳实践吗?

对于实际编程,我发现忽略这些其他方式并只关注特定的调用方式要容易得多。这就是我完成工作的方式,我只是担心其他人可能会以不同的方式称呼它。

我有办法在语言层面做出限制吗?或者我应该?

特别是,我正在尝试编写

my_length
使其适用于

  1. 指定列表,计算长度,以及
  2. 指定长度,返回一个长度为无限槽的列表。
my_length([], 0).
my_length([_|T], A) :- my_length(T, TA), A is TA + 1.

这两种方式都很好,除了当我问相反的问题时它会提示更多答案,然后我们得到堆栈溢出。我们也不能对长度参数进行算术运算,因为它可能未指定。

这只是个案。

prolog
1个回答
0
投票

可以用cut(即感叹号):

list_length(Lst, Len) :-
    nonvar(Len),
    % Commit to this path
    !,
    % Using an accumulator - faster than recursion
    list_length_(Lst, 0, Len),
    % No more than 1 solution
    !.
list_length(Lst, Len) :-
    list_length_(Lst, 0, Len).
    
% Found end of list
list_length_([], Len, Len).
list_length_([_|T], Upto, Len) :-
    % Iterate through list
    Upto1 is Upto + 1,
    list_length_(T, Upto1, Len).

swi-prolog 中的结果:

?- list_length([a,b,c], Len).
Len = 3.

?- list_length(Lst, 3).
Lst = [_, _, _].

?- Lst = [a,b,c], list_length(Lst, Len).
Len = 3.

这避免了不必要的选择点。

© www.soinside.com 2019 - 2024. All rights reserved.