Replace 序言替换

Replace 序言替换,replace,prolog,substitution,meta-predicate,Replace,Prolog,Substitution,Meta Predicate,如何用包含要替换变量的另一个列表替换列表。比如说 rep([x, d, e, z, x, z, p], [x=z, z=x, d=c], R). R = [z, c, e, x, z, x, p] 更换后,x到z和z不会改变 到目前为止,我只做了一个没有列表的 rep([], _, []). rep(L1, H1=H2, L2) :- rep(L1, H1, H2, L2). rep([],_,_,[]). rep([H|T], X1, X2, [X2|L]) :- H=X1,

如何用包含要替换变量的另一个列表替换列表。比如说

rep([x, d, e, z, x, z, p], [x=z, z=x, d=c], R).
R = [z, c, e, x, z, x, p]
更换后,x到z和z不会改变

到目前为止,我只做了一个没有列表的

rep([], _, []).
rep(L1, H1=H2, L2) :-
   rep(L1, H1, H2, L2).

rep([],_,_,[]).
rep([H|T], X1, X2, [X2|L]) :-
   H=X1,
   rep(T,X1,X2,L),
   !.
rep([H|T],X1,X2,[H|L]) :-
   rep(T,X1,X2,L).

我发现你的代码相当混乱。首先,您有rep/3和rep/4,但在传递变量绑定列表的第二个位置没有一个列表。H1=H2不可能与列表匹配,这是检查第二个参数的唯一rep/3子句。如果这是一个课堂作业,看起来你有点落后了,我建议你花点时间在前面的材料上

解决方案比您想象的要简单:

rep([], _, []).
rep([X|Xs], Vars, [Y|Rest]) :-    member(X=Y, Vars), rep(Xs, Vars, Rest).
rep([X|Xs], Vars, [X|Rest]) :- \+ member(X=_, Vars), rep(Xs, Vars, Rest).
我们使用member/2在引号中查找列表中的变量绑定,因为这些是原子,而不是真正的Prolog变量。如果在列表中,Y是替换项,否则我们继续使用X。您可以看到,这具有预期的效果:

?- rep([x, d, e, z, x, z, p], [x=z, z=x, d=c], R).
R = [z, c, e, x, z, x, p] ;
false.
使用或直接使用可使其更高效,并为我们节省一个选择点:

rep([], _, []).
rep([X|Xs], Vars, [Y|Ys]) :- 
  (member(X=Y, Vars), ! ; X=Y), 
  rep(Xs, Vars, Ys).
见:


我发现你的代码相当混乱。首先,您有rep/3和rep/4,但在传递变量绑定列表的第二个位置没有一个列表。H1=H2不可能与列表匹配,这是检查第二个参数的唯一rep/3子句。如果这是一个课堂作业,看起来你有点落后了,我建议你花点时间在前面的材料上

解决方案比您想象的要简单:

rep([], _, []).
rep([X|Xs], Vars, [Y|Rest]) :-    member(X=Y, Vars), rep(Xs, Vars, Rest).
rep([X|Xs], Vars, [X|Rest]) :- \+ member(X=_, Vars), rep(Xs, Vars, Rest).
我们使用member/2在引号中查找列表中的变量绑定,因为这些是原子,而不是真正的Prolog变量。如果在列表中,Y是替换项,否则我们继续使用X。您可以看到,这具有预期的效果:

?- rep([x, d, e, z, x, z, p], [x=z, z=x, d=c], R).
R = [z, c, e, x, z, x, p] ;
false.
使用或直接使用可使其更高效,并为我们节省一个选择点:

rep([], _, []).
rep([X|Xs], Vars, [Y|Ys]) :- 
  (member(X=Y, Vars), ! ; X=Y), 
  rep(Xs, Vars, Ys).
见:


如果您使用SWI Prolog,模块lambda.pl位于此处:您可以编写:

:- use_module(library(lambda)).

rep(L, Rep, New_L) :-
    maplist(\X^Y^(member(X=Z, Rep)
              ->  Y = Z
              ;   Y = X), L, New_L).

如果您使用SWI Prolog,模块lambda.pl位于此处:您可以编写:

:- use_module(library(lambda)).

rep(L, Rep, New_L) :-
    maplist(\X^Y^(member(X=Z, Rep)
              ->  Y = Z
              ;   Y = X), L, New_L).

您应该尝试使代码尽可能简单:

rep([], _, []).
rep([X|Xs], Vs, [Y|Ys]) :-
   ( memberchk(X=V, Vs) -> Y = V ; Y = X ),
   rep(Xs, Vs, Ys).
当然,请注意通过memberchk/2检查变量值的惯用方法

还有一种更惯用的方法:转换列表它是几种语言的基本构造块,Prolog也不例外:

rep(Xs, Vs, Ys) :- maplist(repv(Vs), Xs, Ys).
repv(Vs, X, Y) :- memberchk(X=V, Vs) -> Y = V ; Y = X .

您应该尝试使代码尽可能简单:

rep([], _, []).
rep([X|Xs], Vs, [Y|Ys]) :-
   ( memberchk(X=V, Vs) -> Y = V ; Y = X ),
   rep(Xs, Vs, Ys).
当然,请注意通过memberchk/2检查变量值的惯用方法

还有一种更惯用的方法:转换列表它是几种语言的基本构造块,Prolog也不例外:

rep(Xs, Vs, Ys) :- maplist(repv(Vs), Xs, Ys).
repv(Vs, X, Y) :- memberchk(X=V, Vs) -> Y = V ; Y = X .

以下是如何继续使用和

首先,我们尝试在对K-V的列表中找到一个键。 一个额外的参数具体化搜索成功

pairs_key_firstvalue_t([]       ,_  ,_    ,false).
pairs_key_firstvalue_t([K-V|KVs],Key,Value,Truth) :-
   if_(K=Key,
       (V=Value, Truth=true),
       pairs_key_firstvalue_t(KVs,Key,Value,Truth)).
接下来,我们需要处理未找到的案例:

assoc_key_mapped(Assoc,Key,Value) :-
   if_(pairs_key_firstvalue_t(Assoc,Key,Value),
       true,
       Key=Value).
最后,我们使用以下公式将其组合在一起:


以下是如何继续使用和

首先,我们尝试在对K-V的列表中找到一个键。 一个额外的参数具体化搜索成功

pairs_key_firstvalue_t([]       ,_  ,_    ,false).
pairs_key_firstvalue_t([K-V|KVs],Key,Value,Truth) :-
   if_(K=Key,
       (V=Value, Truth=true),
       pairs_key_firstvalue_t(KVs,Key,Value,Truth)).
接下来,我们需要处理未找到的案例:

assoc_key_mapped(Assoc,Key,Value) :-
   if_(pairs_key_firstvalue_t(Assoc,Key,Value),
       true,
       Key=Value).
最后,我们使用以下公式将其组合在一起:

让我们改进一下,将递归部分移到\u t/4中的find\u first\u中:

为了填充缺失的位和片段,我们定义了密钥对\u t/3:

基于\u t/4中的find\u first\u和key\u pair\u t/3,我们可以这样编写assoc\u key\u mapped/3:

assoc_key_mapped(Assoc,Key,Value) :-
   if_(find_first_in_t(key_pair_t(Key),_-Value,Assoc),
       true,
       Key=Value).
那么,OP的用例仍然有效吗

?- maplist(assoc_key_mapped([x-z,z-x,d-c]), [x,d,e,z,a,z,p], Rs).
Rs = [z,c,e,x,a,x,p].                            % OK. same result as before
在t/4中查找第一个

让我们改进一下,将递归部分移到\u t/4中的find\u first\u中:

为了填充缺失的位和片段,我们定义了密钥对\u t/3:

基于\u t/4中的find\u first\u和key\u pair\u t/3,我们可以这样编写assoc\u key\u mapped/3:

assoc_key_mapped(Assoc,Key,Value) :-
   if_(find_first_in_t(key_pair_t(Key),_-Value,Assoc),
       true,
       Key=Value).
那么,OP的用例仍然有效吗

?- maplist(assoc_key_mapped([x-z,z-x,d-c]), [x,d,e,z,a,z,p], Rs).
Rs = [z,c,e,x,a,x,p].                            % OK. same result as before
在t/4中查找第一个


我承认,当我读到你写的东西时,我忍不住笑了:你应该尽量让代码变得更简单。让我开心:我承认当我读到你写的东西时,我忍不住笑了:你应该尽量让代码变得更简单。make my day:看起来像是一个糟糕的抽象:在其他情况下,第一个值可能是有意义的,而不仅仅是在平等适用时。@false。在列表中的find first项之上构建pairs\u key\u firstvalue\t怎么样?比如说,这个习惯用法?@j4nbur53。不,它不是一个函数,而是一个谓词,一个额外的参数_t是_truth/_truthvalue的缩写,用于将成功/失败反映到原子true/false中。然后,if_/3随后使用此参数将控制流转向正确的方向。@j4nbur53。酷链接。。。我不太明白你之前评论的最后一句话,请详细说明!p_t可以与t一起使用,额外的参数可以是绑定的或未绑定的。你所写的关于p_t与函数f_t相同的内容直指问题的核心:在p_t…,t中,当实例化足够时,变量t最终得到唯一的确定。然而,如果p_t与非地面数据一起使用,则情况可能并非如此,因此我们使用“不”
-为了保持完整性,请及时且仅及时了解样式不确定性。这看起来像是一个糟糕的抽象:可能还有其他情况下第一个值值得关注,而不仅仅是在应用相等时。@false。在列表中的find first项之上构建pairs\u key\u firstvalue\t怎么样?比如说,这个习惯用法?@j4nbur53。不,它不是一个函数,而是一个谓词,一个额外的参数_t是_truth/_truthvalue的缩写,用于将成功/失败反映到原子true/false中。然后,if_/3随后使用此参数将控制流转向正确的方向。@j4nbur53。酷链接。。。我不太明白你之前评论的最后一句话,请详细说明!p_t可以与t一起使用,额外的参数可以是绑定的或未绑定的。你所写的关于p_t与函数f_t相同的内容直指问题的核心:在p_t…,t中,当实例化足够时,变量t最终得到唯一的确定。然而,如果p_t与非地面数据一起使用,则情况可能并非如此,因此,为了保持完整性,我们使用未知类型的不确定性。。。迫切的此外,由于E=X,不必要的弱。@false。谢谢!不用E=X,Truth=true,我可以用E=X,Truth。虽然这适用于成员d_t/3的上述定义,但不适用于成员d_t/3中的exists_。你有什么想法吗?仍将尽快编辑。@false。由于E=X,你所说的弱是什么意思?=/3更好吗?\u t/3中的exists\u使用u作为X,这与=/3不好。。。帮助也就是说,X不能影响P_2的终止。。。迫切的此外,由于E=X,不必要的弱。@false。谢谢!不用E=X,Truth=true,我可以用E=X,Truth。虽然这适用于成员d_t/3的上述定义,但不适用于成员d_t/3中的exists_。你有什么想法吗?仍将尽快编辑。@false。由于E=X,你所说的弱是什么意思?=/3更好吗?\u t/3中的exists\u使用u作为X,这与=/3不好。。。帮助也就是说,X不能影响P_2的终止。