【问题标题】:Uninstantiated variable at end of list in SWI-PrologSWI-Prolog中列表末尾的未实例化变量
【发布时间】:2017-01-21 17:49:55
【问题描述】:

我编写了一个程序来对符号中的数字进行排序,它可以工作,但是在列表末尾给了我一个内存地址,它没有在最后运行。为什么会这样?

separate([],[],[]).
separate([X],X,_):-number(X).
separate([X],_,X).
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S).
separate([X|Y],Z,[X|S]):-separate(Y,Z,S).

咨询?- separate([3,a,b,4,5,c],X,Y).

我明白了:

X = [3, 4, 5|_G2592],
Y = [a, b, c] .

【问题讨论】:

  • 看到答案后不要按Enter,如果按空格键会发生什么。见:Why does SWI-Prolog only give me the first answer?
  • 在第一次学习 Prolog 时不要使用 XY 之类的变量,而是使用更有意义的名称,例如 DigitLetterDigitsLetters、@ 987654332@。一旦你了解发生了什么,你就可以恢复到XY等。

标签: prolog


【解决方案1】:

我提议

separate([],[],[]).

separate([H | T], [H | Tn], Ls) :-
  number(H),
  separate(T, Tn, Ls).

separate([H | T], Ln, [H | Ts]) :-
  \+ number(H),
  separate(T, Ln, Ts).

如果您有一个终止子句separate([],[],[]) 和几个普通子句separate([X|Y],[X|Z],S)separate([X|Y],Z,[X|S]),则不需要半终止子句separate([X],X,_)separate([X],_,X),它们(带有undefined value _) 避免了其中一个列表的统一,您将获得“内存地址”(未统一变量的标识符)。

如果您有一个带有number(X) 的子句,则另一个(替代)子句需要“非数字”检查(即\+ number(X)),否则两个子句都对数字为真,并且您将解决方案相乘,其中数字非数字列表。

【讨论】:

    【解决方案2】:

    那是因为您让列表尾部保持打开状态

    分开([X],X,_):-数字(X)。 分开([X],_,X)。

    问题是:您实际上不需要编写这些语句,您可以省略它们:

    separate([],[],[]).
    separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S).
    separate([X|Y],Z,[X|S]):-separate(Y,Z,S).
    

    这会起作用但它会返回多个结果,并且除了第一个,其余的都是错误的。您应该通过在最后一个子句中添加保护来解决这个问题:

    分离([],[],[])。 分开([X|Y],[X|Z],S):-数(X),分开(Y,Z,S)。 分开([X|Y],Z,[X|S]):-\+ 数字(X),分开(Y,Z,S)。

    如果 Prolog 无法匹配 number(X)\+ number(X) 将成功,\+ 的作用类似于“非”。

    最后一点是,您看到的并不是真正的内存地址:它只是一个未实例化的变量,尽管这当然是一个小问题。

    【讨论】:

    • 不确定它是否是内存地址,但它是我认为的最接近的地址,也感谢您清除它。 \+ 对我来说是未知的,并且从未在我们的脚本中提及。
    • @Streamline: 啊\+ 就像一个“不”(尽管这样说很危险)。例如,如果 Prolog 无法匹配 number(a),则 \+ number(a) 将成功,这并不是说。
    猜你喜欢
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多