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不是[| |]
注意当/2T=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]).