列表是空的,没有被修改 - PROLOG

时间:2017-01-17 16:06:17

标签: prolog

我正在尝试创建一个坐标列表:

insert(X,L,[X|L]). 

% L is a list and Q is a count that define the number of coordinate
% X and Y are the coordinate members
% check if the coordinate already exists
% if exists, R is 0 and if not, R is 1
% if the count is different of 0, I continous generating coordinates, else, I stop

createCoordinates(L,Q) :-
    C is Q,
    random(1,10,X),
    random(1,10,Y),
    convertNumber(X,Z),
    checkCoordinate([Z,Y],L,R),
    (C \== 0 -> (R is 0 -> createCoordinates(L,Q); insert([X,Y],L,A), createCoordinates(A,Q-1)); trace, print(L),print('Done!')).

checkCoordinate(C,L,R) :-
    (member(C,L) -> R is 0; R is 1).

convertNumber(1,'A').
convertNumber(2,'B').
convertNumber(3,'C').
convertNumber(4,'D').
convertNumber(5,'E').
convertNumber(6,'F').
convertNumber(7,'G').
convertNumber(8,'H').
convertNumber(9,'I').
convertNumber(1,'J').

% call createCoordinates
begin :-
    L = [],
    createCoordinates(L,20),
    print(L).

当我在子句中打印列表时,所有元素都存在,但是当我打印出子句时,列表为空。

当我调试时,它是这样的:

debug

可能这是一个愚蠢的错误,但我是prolog的新手,这对我来说毫无意义。

1 个答案:

答案 0 :(得分:2)

您需要了解的有关等声明性语言的一个基本方面是,它们是 - 声明性的:一旦您定义一个变量,你可以不再改变它的价值

换句话说,编写I = 1,然后编写I = 4会导致程序失败。

在你的" main"你写道:

begin :-
    L = [],
    createCoordinates(L,20),
    print(L).

在这里,您看到完全实例化 L,这意味着从现在开始,L始终为[]

因此,通常通过定义谓词来解决问题:

predicate(Some,Parameters,Prior,Post)

在<{em> 之后Post上的某个效果Prior上的Post是一个值 {注意这并不意味着你只能计算Prior createCoordinates/2 1}}:Prolog中的大多数谓词都允许你去另一个方向。)

因此,对于您的情况,您必须将createCoordinates/3重写为createCoordinates(Lin,Q,Lout)

Lout

现在你需要定义这个谓词。您可以通过改变它来完成此操作:

createCoordinates(Lin,Q,Lout) :-
    C is Q,
    random(1,10,X),
    random(1,10,Y),
    convertNumber(X,Z),
    checkCoordinate([Z,Y],Lin,R),
    (C \== 0
     -> (R is 0
        -> createCoordinates(Lin,Q,Lout)
        ;  (insert([X,Y],Lin,A),
           createCoordinates(A,Q-1,Lout))
        )
    ; (trace,
       print(Lin),
       print('Done!'),
       Lout = Lin)
    ).

我冒昧地重新格式化你的代码。如您所见,谓词和调用现在使用'Done!'参数。最后,如果我们Lout = Lin,我们设置Lout,这意味着现在Lin获取我们称之为谓词的trace/0的值。

你用:

来称呼它
begin :-
    Lin = [],
    createCoordinates(Lin,20,Lout),
    print(Lout).

消除print/1和内部?- begin. [[9,7],[7,1],[3,4],[7,7],[1,3],[9,1],[1,9],[8,8],[5,3],[8,3],[8,1],[6,3],[2,9],[3,6],[8,9],[6,6],[8,4],[6,3],[7,9],[4,1]] 语句会产生:

createCoordinates/3

话虽这么说,你的程序显然是用命令式思维模式编写的:这不是中的程序看起来的样子。编写createCoordinates(Lin,Q,Lin) :- Q < 0. createCoordinates(Lin,Q,Lout) :- Q1 is Q-1, random(1,10,X), random(1,10,Y), convertNumber(X,Z), checkCoordinate([Z,Y],Lin,1), insert([X,Y],Lin,A), createCoordinates(A,Q1,Lout). 的方式肯定可以改进。

更好的版本是:

Spinner

然而,即使有了这些改进,你仍然需要进行大量的重构。