括号如何工作?

时间:2012-08-11 14:16:00

标签: prolog

我编写了一个算法并尝试在Prolog中实现它,但我发现括号不能按预期工作:写入的内容并不是在退出括号之前完成的。这是代码:

%1. If the first member of L1 is smaller than L2
%     A. If the first member of L1 is not equal to Last
%            Than: A.1 Add the first member of L1 to the first member of NL
%                  Begin recurssion on the resumption of L1, L2 resumption of NL
%                  and Last from L1.
%            Else: A.2  begin the recursion on resumption of L1, L2 with the
%                       first member and L3 with the first member.
%  2. If the first member in L1 is equal to the first member of L2,
%             Than: Start recursion on resumption of L1 and L2 (with its first
%                   member) and Last = *.
%  3. If the first member of L1 is bigger than the first membber of L2
%             Than: begin recursion on L1 with the first member, resumption of
%             L2 and Last = x. %(x != * only for debugging)
%  

                              */
make_list([X1|L1], [X2|L2], [X3|NewL], Last) :-
    (
        X1 < X2,
        (
            X1 \= Last,   %A
            X3=X1;
            make_list(L1, [X2|L2], NewL, X1) %B
        ),  %Why those parenthesis do not work as expected?

        ! %green cut
    );
    (
        X1=X2,
        make_list(L1, [X2|L2], [X3|NewL], *)
    ),
    !
    ;
    make_list([X1|L1], L2, [X3|NewL], *).

我的问题是如何使其按预期工作,为什么BA完成后无效?毕竟它也在同一个括号中,例如:

?- make_list([6,6,10,20],[10,25,30],L, -).
L = [6|_G849]  % (should be [6,20]).

EDIT1:make_list应该找到L1中不在L2的所有成员并将它们放在NewL中,而Last将最后一个成员存储在{ {1}}已解析。

EDIT2:不 - &gt;是允许的(这是如何工作)。如果有人能告诉我如何在prolog中表达,那可能会很棒。

2 个答案:

答案 0 :(得分:1)

我怀疑&#34;绿色切割&#34;你的不是绿色的;你有

( A ; B ), !

所以第一次退出(A ; B)时,如果A成功,B再也不会被尝试 - 这就是!在这里所说的内容:don&# 39;再试一次。

如果您也想尝试B,请移除剪切!

If-then-else是:

ifte(A,B,C):- A, B.
ifte(A,B,C):- \+A, C.

我们可以使用not

为我们留出cut
ifte(A,B,C):- A, !, B.
ifte(A,B,C):- C.

关于您的代码:我们使用逗号and then表达A,B。输出最后一个最容易使用工作谓词,附加参数,&#34; see-last&#34 ;;在最后看到的基础情况和输出将统一。

答案 1 :(得分:1)

简而言之:!/0适用于谓词级别:此处您希望将其应用于某些块级别,其中块将由()分隔。 Prolog中不存在应用于块的切割概念。剪切将擦除所有遇到的选择点,直到它在谓词中的位置。

而不是使用大量(;)/2用法编写代码,考虑引入新的子句,以提高可读性(正是因为我们不喜欢括号并找出(;)/2(,)/2优先级):

c :- A; B.

可以写

c :- A.
c :- B.

这种方式通常会更好。最好是轻松生成代码,更好地维护代码,阅读代码并扩展代码。

我没有深入研究你的谓词或任何东西,只是想提到这两件事。