Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Prolog 我如何重写下面的内容,以便它使用if\ux?_Prolog - Fatal编程技术网

Prolog 我如何重写下面的内容,以便它使用if\ux?

Prolog 我如何重写下面的内容,以便它使用if\ux?,prolog,Prolog,我正在做一些简单的练习来感受这种语言 is_list([]). is_list([_|_]). my_flatten([],[]). my_flatten([X|Xs],RR) :- my_flatten(Xs,R), (is_list(X), !, append(X,R,RR); RR = [X | R]). 下面是一个使用cut的版本,用于将列表展平一级的谓词 my_flatten([],[]). my_flatten([X|Xs],RR) :- my_flatten(

我正在做一些简单的练习来感受这种语言

is_list([]).
is_list([_|_]).

my_flatten([],[]).
my_flatten([X|Xs],RR) :-
   my_flatten(Xs,R),
   (is_list(X), !, append(X,R,RR); RR = [X | R]).
下面是一个使用cut的版本,用于将列表展平一级的谓词

my_flatten([],[]).
my_flatten([X|Xs],RR) :-
   my_flatten(Xs,R),
   if_(is_list(X), append(X,R,RR), RR = [X | R]).

下面是我想写它的方式,但它不起作用。
is_list(X)=true
if_u
条件相同。我打算如何在这里使用
if?

在Prolog中,其他语言中
if…then…else…
的等价物是:

(condition -> if-true; if-false)
或者,我们可以使用以下方法进行递归展平:

my_flatten([],[]).
my_flatten([X|Xs],RR) :- 
    my_flatten(Xs,R),
    (  flatten(X, XF)
    -> append(XF,R,RR)
    ; RR = [X | R] ).
my_展平([],[])。
my|u展平([X | Xs],RR):-
my_展平(Xs,R),
(展平(X,XF)
->附加(XF、R、RR)
;RR=[X | R])。
您的用于。

(抱歉,我略过了此部分)

  • 请参阅。它清楚地表明,它是平坦的,但你和@Willem产生:
  • 这里给出的解决方案成功了
  • 您对
    is_list/1
    的定义适用于
    is_list([a | non_list])
    。通常,我们希望这样做失败
您需要的是一个安全谓词来测试列表。让我们先集中精力:

是列表/1
有什么问题吗?它是非单调的,就像

虽然原始查询成功,但它的泛化却意外失败。在Prolog的单调部分,我们期望泛化会成功(或循环,产生错误,耗尽所有资源,但永远不会失败)

现在,您有两个选项可以改善这种极不理想的情况:

用安全的推论保持安全,
\u si
! 只需将的定义替换为
is_list/1
。在有问题的情况下,您的程序现在将由于实例化错误而中止,这意味着“很抱歉,我不知道如何回答此查询”。为你的回答感到高兴!你不会被错误的答案误导

换句话说:
(If\u 0->Then\u 0;Else\u 0)
,只要
If\u 0
正确处理实例化不足的情况(并且不引用用户定义的程序,否则您将再次处于非单调行为)

这里有这样一个定义:

my_flatten(Es, Fs) :-
   list_si(Es),
   phrase(flattenl(Es), Fs).

flattenl([]) --> [].
flattenl([E|Es]) -->
   ( {list_si(E)} -> flattenl(E) ;  [E] ),
   flattenl(Es).

?- my_flatten([a, [b, [c, d], e]], X).
X = [a,b,c,d,e].
:- meta_predicate( if_(1, 2, 2, ?,?) ).

my_flatten(Es, Fs) :-
   phrase(flattenl(Es), Fs).

flattenl([]) --> [].
flattenl([E|Es]) -->
   if_(list_t(E), flattenl(E), [E] ),
   flattenl(Es).

if_(C_1, Then__0, Else__0, Xs0,Xs) :-
   if_(C_1, phrase(Then__0, Xs0,Xs), phrase(Else__0, Xs0,Xs) ).

?- my_flatten([a|_], [e|_]).
   false.

?- my_flatten([e|_], [e|_]).
   true
;  true
;  true
...

?- my_flatten([a|Xs], [a]).
   Xs = []
;  Xs = [[]]
;  Xs = [[],[]]
...

?- my_flatten([X,a], [a]).
   X = []
;  X = [[]]
;  X = [[[]]]
;  X = [[[[]]]]
...

?- my_flatten(Xs, [a]).
*** LOOPS *** at least it does not fail
因此
(If\u 0->Then\u 0;Else\u 0)
有两个缺点:If\u 0
的条件可能会导致实例化不足,而
Else\u 0
可能是非单调性的根源。但除此之外,它是有效的。那么,我们为什么想要更多呢? 在许多更一般的情况下,这个定义现在会反驳:“实例化错误”!虽然没有错误,但这仍然可以改进。这个练习不是这方面的理想示例,但我们将尝试一下

使用具体化的条件 为了使用
if\u3
,您需要一个具体化的条件,即一个将其真值作为显式额外参数的定义。让我们称之为
list\u t/2

?- list_t([a,b,c], T).
T = true.

?- list_t([a,b,c|non_list], T).
T = false.

?- list_t(Any, T).
   Any = [],
   T = true
;  T = false,
   dif(Any,[]),
   when(nonvar(Any),Any\=[_|_])
;  Any = [_],
   T = true
;  Any = [_|_Any1],
   T = false,
   dif(_Any1,[]),
   when(nonvar(_Any1),_Any1\=[_|_])
;  ...
因此
list\u t
还可以用于枚举所有
true
false
情况。让我们看一下:

  • T=true,Any=[]
    这是空列表
  • T=false,dif(Any,[]),Any不是[| |]
    注意当/2
  • T=true,Any=[\u]
    这是包含一个元素的所有列表
  • T=true,Any=[124; 124; Any1]…
    意思是:我们从一个元素开始,但没有列表
  • 最后,具体化的定义:

    my_flatten(Es, Fs) :-
       list_si(Es),
       phrase(flattenl(Es), Fs).
    
    flattenl([]) --> [].
    flattenl([E|Es]) -->
       ( {list_si(E)} -> flattenl(E) ;  [E] ),
       flattenl(Es).
    
    ?- my_flatten([a, [b, [c, d], e]], X).
    X = [a,b,c,d,e].
    
    :- meta_predicate( if_(1, 2, 2, ?,?) ).
    
    my_flatten(Es, Fs) :-
       phrase(flattenl(Es), Fs).
    
    flattenl([]) --> [].
    flattenl([E|Es]) -->
       if_(list_t(E), flattenl(E), [E] ),
       flattenl(Es).
    
    if_(C_1, Then__0, Else__0, Xs0,Xs) :-
       if_(C_1, phrase(Then__0, Xs0,Xs), phrase(Else__0, Xs0,Xs) ).
    
    ?- my_flatten([a|_], [e|_]).
       false.
    
    ?- my_flatten([e|_], [e|_]).
       true
    ;  true
    ;  true
    ...
    
    ?- my_flatten([a|Xs], [a]).
       Xs = []
    ;  Xs = [[]]
    ;  Xs = [[],[]]
    ...
    
    ?- my_flatten([X,a], [a]).
       X = []
    ;  X = [[]]
    ;  X = [[[]]]
    ;  X = [[[[]]]]
    ...
    
    ?- my_flatten(Xs, [a]).
    *** LOOPS *** at least it does not fail
    
    这对我很有用:

    myflat([], []).
    
    myflat([H|T], L) :-
      myflat(H, L1),
      myflat(T, L2),
      append(L1, L2, L).
    
    myflat(L, [L]).
    

    如果定义了
    ,那么
    在哪里?我已经通过了,所以我从链接中获得了reif库,并手动将其放入主库目录中。我使用的是SWI Prolog。但这是用于具体化约束的。这意味着
    is_list
    谓词将有两个参数,第二个参数是布尔值。啊,我明白了。那就可以用你给我看的东西了。作为这方面的新手,我并不真正理解为什么其他构造有缺陷的所有论点,但它确实让我印象深刻,我应该在必要时避免像cut这样的东西。因为这里的常规if很好,我接受你的答案。
    myflat([[[1]]],L)。
    给出了15个答案,描述了10种解决方案。据我所知,应该只有一种解决方案:
    X=[1]
    list_t(Es, T) :-
       if_( Es = []
          , T = true
          , if_(nocons_t(Es), T = false, ( Es = [_|Fs], list_t(Fs, T) ) )
          ).
    
    nocons_t(NC, true) :-
       when(nonvar(NC), NC \= [_|_]).
    nocons_t([_|_], false).
    
    :- meta_predicate( if_(1, 2, 2, ?,?) ).
    
    my_flatten(Es, Fs) :-
       phrase(flattenl(Es), Fs).
    
    flattenl([]) --> [].
    flattenl([E|Es]) -->
       if_(list_t(E), flattenl(E), [E] ),
       flattenl(Es).
    
    if_(C_1, Then__0, Else__0, Xs0,Xs) :-
       if_(C_1, phrase(Then__0, Xs0,Xs), phrase(Else__0, Xs0,Xs) ).
    
    ?- my_flatten([a|_], [e|_]).
       false.
    
    ?- my_flatten([e|_], [e|_]).
       true
    ;  true
    ;  true
    ...
    
    ?- my_flatten([a|Xs], [a]).
       Xs = []
    ;  Xs = [[]]
    ;  Xs = [[],[]]
    ...
    
    ?- my_flatten([X,a], [a]).
       X = []
    ;  X = [[]]
    ;  X = [[[]]]
    ;  X = [[[[]]]]
    ...
    
    ?- my_flatten(Xs, [a]).
    *** LOOPS *** at least it does not fail
    
    myflat([], []).
    
    myflat([H|T], L) :-
      myflat(H, L1),
      myflat(T, L2),
      append(L1, L2, L).
    
    myflat(L, [L]).