程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Prolog flatten/2 实现大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决Prolog flatten/2 实现?

开发过程中遇到Prolog flatten/2 实现的问题如何解决?下面主要结合日常开发的经验,给出你关于Prolog flatten/2 实现的解决方法建议,希望对你解决Prolog flatten/2 实现有所启发或帮助;

这是我对 flatten/2 的实现:

flt([],[]).
flt([H|L],[H|X]):-
    not(is_List(H)),flt(L,X).
flt([H|L],X):-
    append(R,F,X),flt(H,R),F).

给出了预期的结果:

?- flt([1,[2,3,[4,5],6],7],X).
X = [1,2,4,5,6,7]

但是,当我点击 ; 时超出了堆栈限制。为什么会发生这种情况?无限递归在哪里?

谢谢。

解决方法

问题是您调用 append(R,F,X) 时仅使用 未实例化 变量。

flt(+List,-Flatlist) 只有一种解决方案。然而,在回溯时,append(R,X) 被一次又一次地尝试,却没有找到其他解决方案......

你可以通过询问来测试这个

?- append(R,X).
R = [],F = X ;
R = [_948],X = [_948|F] ;
R = [_948,_960],X = [_948,_960|F] ;
R = [_948,_960,_972],_972|F] ;
R = [_948,_972,_984],_984|F] ;
R = [_948,_984,_996],_996|F] 
...

解决方案是重新排列第三个子句中的目标:

flt([H|L],X):-
    flt(H,R),flt(L,F),append(R,X).

这是一个很好的例子,说明 Prolog 不是纯粹的声明性,因为它通过简单的时间顺序回溯来实现解析会强制语言的过程特征。


为了说明问题,请查看此跟踪(为了强调循环问题,我跳过了很多):

[trace]  ?- flt([[a]],X).
   Call: (8) flt([[a]],_680) ? creep
^  Call: (9) not(is_list([a])) ? creep
^  Fail: (9) not(user:is_list([a])) ? creep
   Redo: (8) flt([[a]],_680) ? creep
   Call: (9) lists:append(_904,_906,_680) ? creep
   Exit: (9) lists:append([],_680,_680) ? creep
   Call: (9) flt([a],[]) ? skip
   Fail: (9) flt([a],[]) ? creep
   Redo: (9) lists:append(_904,_680) ? creep
   Exit: (9) lists:append([_890],_898,[_890|_898]) ? creep
   Call: (9) flt([a],[_890]) ? skip
   Exit: (9) flt([a],[a]) ? creep
   Call: (9) flt([],_898) ? skip
   Exit: (9) flt([],[]) ? creep
   Exit: (8) flt([[a]],[a]) ? creep
X = [a] ;
   Redo: (9) flt([a],[_890]) ? skip
   Fail: (9) flt([a],[_890]) ? creep
   Redo: (9) lists:append([_890|_892],_918,[_890|_898]) ? creep
   Exit: (9) lists:append([_890,_902],_910,[_890,_902|_910]) ? creep
   Call: (9) flt([a],_902]) ? skip
   Fail: (9) flt([a],_902]) ? creep
   Redo: (9) lists:append([_890,_902|_904],_930,_902|_910]) ? creep
   Exit: (9) lists:append([_890,_902,_914],_922,_914|_922]) ? creep
   Call: (9) flt([a],_914]) ? skip
   Fail: (9) flt([a],_914]) ? creep
   Redo: (9) lists:append([_890,_914|_916],_942,_914|_922]) ? creep
   Exit: (9) lists:append([_890,_914,_926],_934,_926|_934]) ? creep
   Call: (9) flt([a],_926]) ? skip
   Fail: (9) flt([a],_926]) ? creep
   Redo: (9) lists:append([_890,_926|_928],_954,_926|_934]) ? creep
   Exit: (9) lists:append([_890,_926,_938],_946,_938|_946]) ? creep
   Call: (9) flt([a],_938]) ? skip
   Fail: (9) flt([a],_938]) ? creep
   Redo: (9) lists:append([_890,_938|_940],_966,_938|_946]) ? creep
   Exit: (9) lists:append([_890,_938,_950],_958,_950|_958]) ? creep
   Call: (9) flt([a],_950]) ? skip
   Fail: (9) flt([a],_950]) ? creep
   Redo: (9) lists:append([_890,_950|_952],_978,_950|_958]) ? 

此图以图形方式显示。要求其他答案后会发生什么情况会显示为红色。

Prolog flatten/2 实现


另一种可能的解决方案是添加剪辑:

flt([],[]).
flt([H|L],[H|X]):-
    not(is_list(H)),X),!.

flt([H|L],X):-
    append(R,flt(H,!,F).

大佬总结

以上是大佬教程为你收集整理的Prolog flatten/2 实现全部内容,希望文章能够帮你解决Prolog flatten/2 实现所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: