使用递归方法并在 Prolog 中返回列表

Using recursion method and returning a list in Prolog

给定一个列表 L1、位置 P、元素 A。我正在尝试 return 一个新列表,其中将元素 A 添加到列表 L1 和 return 中的位置 P 中,答案如下:

?- add_member(1,3,[2,3,4,5],A).

X=[2,3,1,4,5].

这是我的代码:

 add_member(X, P, [H|T], NewList) :-
  (P>1, 
    write('p>1 start | '),
    P1 is P-1, 
    add_member(X, P1, T, Newlist1), 
    NewList is [H, Newlist1]), 
    write('p>1 end ');
  (P=1, 
    write('p=1 start | '), 
    NewList is [X,H|T], 
    write('p=1 end | ')).

这里P是位置,X是要插入的元素。我已经使用 write('---') 来了解代码的工作原理(如调试)。 这是它的输出(有错误):

?- add_member(1,3,[2,3,4,5],x).
p>1 start | p>1 start | p=1 start | 
ERROR: Type error: `[]' expected, found `[1,4,5]' (a list) ("x" must hold one character)
ERROR: In:
ERROR:   [13] _22972 is [1,4|...]
ERROR:   [12] add_member(1,1,[4,5],_23016) at /mnt/c/Users/mill/Documents/q2.pl:1
ERROR:   [11] add_member(1,2,[3,4|...],_23058) at /mnt/c/Users/mill/Documents/q2.pl:5
ERROR:   [10] add_member(1,3,[2,3|...],x) at /mnt/c/Users/mill/Documents/q2.pl:5
ERROR:    [9] toplevel_call(user:user: ...) at /usr/lib/swi-prolog/boot/toplevel.pl:1117

这里,q2.pl是文件名,toplevel.pl是不可访问的。我正在为 linux (wsl) 使用 windows 子系统。

如何完成代码?我在这里缺少一个概念吗?

is/2 是一个内置谓词,它要求第二个参数是可算术解析的项(示例:3+67*3)。

在您的示例中,您使用 NewList is [H, Newlist1],其中第二个参数是列表而不是算术表达式。因此你会得到一个类型错误。您应该改用匹配运算符 =

你的代码的第二个问题是 [H, Newlist1] 构建了一个嵌套列表(它是一个长度为 2 的列表,第一个元素是 H,第二个是列表 Newlist1。这是您的代码的更正版本:

add_member(X, P, [H|T], NewList) :-
  (P>1,
    write('p>1 start | '),
    P1 is P-1,
    add_member(X, P1, T, Newlist1),
    NewList = [H|Newlist1],
    write('p>1 end '))
  ;
  (P=1,
    write('p=1 start | '),
    NewList = [X,H|T],
    write('p=1 end | ')).

再说两句:

  • 在空列表的第一个位置插入元素也应该被捕获。

  • 不建议在具有多个普通替代代码的 Prolog 子句中使用析取 (;)(至少应谨慎使用)。因此,最好将您的子句分成两个子句(一个用于 P=1,一个用于 P>1):

     add_member(X, 1, List, [X|List]).
     add_member(X, P, [H|T], [H|NewList]) :-
         P>1,
         P1 is P-1,
         add_member(X, P1, T, NewList).