在Prolog中使用差异列表追加元素时出现问题
我在中找到了此Prolog代码,它使用差异列表实现了一个队列:在Prolog中使用差异列表追加元素时出现问题,prolog,difference-lists,Prolog,Difference Lists,我在中找到了此Prolog代码,它使用差异列表实现了一个队列: %%空队列(-queue) %排空队 空_队列(队列(0,Q,Q))。 %%队列头(?队列,队列头,队列0) %已移除标头的队列为队列0 队列头(队列(s(X),[H | Q],Q0),H,队列(X,Q,Q0))。 %%队列最后(+Queue0,+last,-queue) %Queue0是队列,最后一个在后面 最后一个队列(队列(X,Q,[L | Q0]),L,队列(s(X),Q,Q0))。 做这样的事情,它的工作如预期: ...
%%空队列(-queue)
%排空队
空_队列(队列(0,Q,Q))。
%%队列头(?队列,队列头,队列0)
%已移除标头的队列为队列0
队列头(队列(s(X),[H | Q],Q0),H,队列(X,Q,Q0))。
%%队列最后(+Queue0,+last,-queue)
%Queue0是队列,最后一个在后面
最后一个队列(队列(X,Q,[L | Q0]),L,队列(s(X),Q,Q0))。
做这样的事情,它的工作如预期:
..., empty_queue(Q), queue_last(Q, 999, Q_), writeln(Q_), ....
我得到
queue(s(0),[999|_3076],_3076)
同样有趣的是,如果我用这个片段观察Q
的值:
empty_queue(Q), writeln(Q), queue_last(Q, 999, Q_), writeln(Q)
我得到:
queue(0,_3750,_3750)
queue(0,[999|_3758],[999|_3758])
我想应该是这样的,因为差异导致空列表,所以它们在某种程度上是等价的
问题是,在发出命令之后
queue_last(Q, 999, Q_)
我不能重复使用Q
来创建Q\uu
,例如:
empty_queue(Q), queue_last(Q, 999, Q_), queue_last(Q, 888, Q__)
因为queue_last(queue(X,Q[L|Q0]),L,queue(s(X),Q,Q0))的绑定失败。
L = 888, L = 999 (tries to be both)
我怎样才能解决这个问题?有解决办法吗?(始终使用差异列表)
我不能重复使用Q
来创建Q\uuu
这是因为您必须使用“线程化”的新结构,您称之为Q
。旧的Q
是燃烧器,必须丢弃。它不再正确地描述“差异列表”
?-空队列(Q1),
最后一个队列(Q1、999、Q2),
最后排队(第二季度、第888季度、第三季度)。
Q1=队列(0、[999888|||12414]、[999888|12414]),%
Q2=队列(s(0),[999888||||12414],[888||12414]),%
Q3=队列(s(s(0)),[999888 | 14714],_14714)。%正确的,有效的
在清空队列(Q1)
呼叫后,这是Q1
:
队列
├── arg 0:0
├── arg 1:-----+-->
| |
└── arg 2:----+
最后一次(Q1、999、Q2)呼叫后,这是Q1
和Q2
:
Q1
(无效)
队列
├── arg 0:0
├── arg 1:-----+->[|]
| | / \
| | 999
| |
└── arg 2:----+
Q2
(有效)
队列
├── arg 0:s(0)
├── arg 1:----------->[|]
| / \
| 999
| ^
| |
└── arg 2:----------------+
最后一次(Q2、888、Q3)呼叫后,这是Q1
,Q2
和Q3
:
Q1
(无效)
队列
├── arg 0:0
├── arg 1:-----+->[|]
| | / \
| | 999 [|]
| | / \
└── arg 2:---+888
Q2
(无效)
队列
├── arg 0:s(0)
├── arg 1:----------->[|]
| / \
| 999 [|][|]
| / \
| 999 [|]
| / \
| 888
| ^
| |
└── arg 2:----------------------+
无法重新分配Prolog变量。你不能重复使用它们。我不知道调用变量“burned”是否有很大帮助,它们不是burned,而是绑定到一个具体的值
不要使用“write”和friends,除非您正在进行一些复杂的打印样式调试。在顶层进行尝试,无论如何你都会把所有内容打印出来。下面是如何使用此队列实现。请注意,我使用的是Q0
、Q1
、Q2
,等等,因为当有多个下划线时,我很难计数下划线
a
,然后在队列末尾的b
:
?-空队列(Q0),队列最后一个(Q0,a,Q1),队列最后一个(Q1,b,Q2)。
Q0=队列(0[a,b|u 15096],[a,b|u 15096]),
Q1=队列(s(0),[a,b|25096],[b|25096]),
Q2=队列(s(s(0)),[a,b|u 15096],_15096)。
将a
排队,然后将b
排队,然后弹出您排队的第一个值(顺序):
?-空队列(Q0),队列最后一个(Q0,a,Q1),队列最后一个(Q1,b,Q2),
队列头(Q2,弹出,Q3)。
Q0=队列(0[a,b|u 17772],[a,b|u 17772]),
Q1=队列(s(0),[a,b|u 17772],[b|u 17772]),
Q2=队列(s(s(0)),[a,b | u 17772],_17772),
砰砰的一声,
Q3=队列(s(0),[b | _17772],_17772)。
向前推两次,然后弹出(顺序):
?-空队列(Q0)、队列头(Q1,x,Q0)、队列头(Q2,y,Q1),
队列头(Q2,弹出,Q3)。
Q0=队列(0,_21688,_21688),
Q1=Q3,Q3=队列(s(0),[x | 21688],21688),
Q2=队列(s(s(0)),[y,x | u 21688],_21688),
弹出=y。
我在你问题下方的评论中链接的答案(这里又是:)详细解释了这是如何工作的。它还有到其他相关Q/a等的链接。好的,我明白了,如果我想使用“烧掉的”一个队列两次,以便从初始队列生成两个不同的队列,那么有什么解决方法吗?@但是为什么你可以用重命名(新鲜)变量创建深度副本,即新分配的“空单元格”。但是如果我要复制一个列表,为什么我不应该首先使用append?@但是为什么“差异列表”的想法是不复制t0处存在的结构,而只是“在末尾追加”,在尚未定义的位置增长结构。但是,为了保持差异列表中名为tip和fin的变量的“差异列表”,您必须切换到新的上下文。这通常是通过尾部递归调用完成的。在使用“队列”的代码中,这是模糊的,因为它看起来像是面向对象的或功能性的,但实际上不是,您不能使用“旧队列”。@但是为什么如果您使用
append/2
,那么t0
处存在的结构将被完全定义(在fin处没有空单元格),并且您可以永远保留它,但它也会被删除