如何“返回"序言中的值? [英] How to 'return' a value in prolog?
问题描述
我想做的是将两个列表中的元素追加到另一个列表中,最后在控制台中获取新列表的值. 我的列表是:A = [a,b]; B(对列表)= [(c,cc),(a,aa),(b,bb)] 如果第一个元素与对的第一个元素匹配(字典原理),我想添加列表B对的第二个元素(我希望将所有这些元素添加到控制台将输出的空列表中). 到目前为止,我的情况是这样(X是空列表):
What I am trying to do is append elements from two lists into another and in the end get the value of the new list out in console. My lists are : A = [a, b]; B(list of pairs) = [(c, cc), (a, aa), (b, bb)] I want to add the second element of pair of list B if the first element matches the first element of pair (dictionary principle) And I want all those elements to be added in an empty list which the console would output. What I have so far is this (X would be the empty list):
aa(_, [], _) :-
true.
aa([H|T], [(A, B)|T2], X) :-
H == A ->
append([B], X, X2), aa([H|T], T2, X2);
aa([H|T], T2, X).
在控制台中,我输入:read(X), trace,aa([a, b], [(c, cc), (a, aa), (b, bb)], X), write(X).
In console I'm typing: read(X), trace,aa([a, b], [(c, cc), (a, aa), (b, bb)], X), write(X).
但是它一直返回X的[]值.如果我要X,如何获得X2的值作为输出? 这是跟踪输出:
But it keeps returning the [] value of X. How can I get the value of X2 as output if I am asking for X? Here is the trace output:
Call:aa([a, b], [(c,cc), (a,aa), (b,bb)], [])
Call:a==c
Fail:a==c
Redo:aa([a, b], [(c,cc), (a,aa), (b,bb)], [])
Call:aa([a, b], [(a,aa), (b,bb)], [])
Call:a==a
Exit:a==a
Call:lists:append([aa], [], _2110)
Exit:lists:append([aa], [], [aa])
Call:aa([a, b], [(b,bb)], [aa])
Call:a==b
Fail:a==b
Redo:aa([a, b], [(b,bb)], [aa])
Call:aa([a, b], [], [aa])
Exit:aa([a, b], [], [aa])
Exit:aa([a, b], [(b,bb)], [aa])
Exit:aa([a, b], [(a,aa), (b,bb)], [])
Exit:aa([a, b], [(c,cc), (a,aa), (b,bb)], [])
Call:write([])
[]
Exit:write([])
推荐答案
将;
放在行尾不是一个好主意,很容易忽略它.我希望使用其他格式,请参见下文.对于您的问题,您以错误的顺序输入了append/3
的参数. X2
是递归调用的中间结果,而您要返回"的结果是此X2
与元素B
的组合:
It's not a good idea to put the ;
at the end of a line, it is very easy to overlook it. I prefer a different format, see below. As for your question, you have the arguments to append/3
in the wrong order. X2
is the intermediate result from the recursive call, and the result you want to "return" is the combination of this X2
with the element B
:
aa(_, [], _) :-
true.
aa([H|T], [(A, B)|T2], X) :-
( H == A
-> append([B], X2, X), aa([H|T], T2, X2)
; aa([H|T], T2, X) ).
目标append([B], X2, X)
可以更清晰地写为X = [B|X2]
.
The goal append([B], X2, X)
can be written more clearly as X = [B|X2]
.
这解决了眼前的问题,但尚未解决整个谓词:
This fixes the immediate problem, but not yet the whole predicate:
?- aa([a, b], [(c, cc), (a, aa), (b, bb)], X).
X = [aa|_G22] ;
false.
您将第一个参数分解为[H|T]
,但实际上并未对此列表进行递归,因此您永远不会查看b
及其对列表中的对应元素.
You decompose the first argument into [H|T]
but don't actually do a recursion over this list, so you never look at b
and its corresponding element in the list of pairs.
这是完成整件事的一种简单方法:
Here's a simple way to do the whole thing:
aa([], _Pairs, []).
aa([Key|Keys], Pairs, Values) :-
( member((Key, Value), Pairs)
-> aa(Keys, Pairs, Values0),
Values = [Value|Values0]
; aa(Keys, Pairs, Values) ).
此处的主要见解是,一旦您知道Key
,就可以在对列表中寻找对(Key, Value)
. Value
尚未绑定到值,并且如果列表包含一对第一个元素为Key
的对,则会由member/2
实例化.这就是统一的力量!
The key insight here is that once you know a Key
, you can look for a pair (Key, Value)
in your list of pairs. Value
is not bound to a value yet and will be instantiated by member/2
if it the list contains a pair whose first element is Key
. This is the power of unification!
这似乎可行:
?- aa([a, b], [(c, cc), (a, aa), (b, bb)], X).
X = [aa, bb].
最后,您可能不想在此之前输入read(X)
,因为这意味着用户必须预测解决方案!
Finally, you probably don't want to have a read(X)
before this, since that means that the user must predict the solution!
这篇关于如何“返回"序言中的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!