繁体   English   中英

序言,改变表达中的原子

[英]prolog, changing atoms in expression

我的任务是编写一个谓词subst(T,A,V,R) ,它将表达式T中原子A所有出现更改为原子V ,结果显示为R

例如:

subst(object(one, two),one,three,R). //R=object(three,two).
susbt(a+1,a,2,R). //R=2+1.

使用这种方法可能很容易:我使用T=..L将表达式更改为 list ,然后将L每个元素与A进行比较,如果它们相同,我可以将其更改为V 最后,我可以逆转第一个动作(再次获得表达式),但我不知道如何处理这样的情况: subst((a+1)*(b+3),a,2,W) // ?

T=..L类的东西开始,我可以得到[*,a+1,b+3] ,但是现在如果我想将a更改为2 ,我无法检查L每个连续项目,因为其中一些不是简单的原子/数字。 现在我的问题是,是否有任何内置谓词来检查列表中的元素是否类似于: a1等,但不是a+1 我的意思是如果我不想先检查它是否是原子,然后再检查它的数量。

或者也许有一些更简单的方法来解决这个问题?

EDIT1:感谢您的评论。 我到目前为止:

subst(T,A,V,R):-T=..L,make_simple(L,L1),replace(L1,A,V,L2),to_exp(L2,R).

make_simple([],[]).
make_simple([H|T],[H|W]):-atom(H),make_simple(T,W),!.
make_simple([H|T],[H|W]):-number(H),make_simple(T,W),!.
make_simple([H|T],[W1|W2]):- \+atom(H),\+number(H),H=..H1,make_simple(H1,W1),make_simple(T,W2).

replace([],_,_,[]).
replace([A|T],A,V,[V|W]):- replace(T,A,V,W),!.
replace([H|T],A,V,[H|W]):- H\=A,\+is_list(H),replace(T,A,V,W),!.
replace([H|T],A,V,[W1|W2]):-H\=A, is_list(H),replace(H,A,V,W1),replace(T,A,V,W2),!.

to_exp([],[]).
to_exp([H|T],[H|W]):- \+is_list(H),to_exp(T,W),!.
to_exp([H|T],[W1|W2]):- is_list(H), (what next?)

不幸的是,我现在不知道如何将这些部分放在to_exp部分中。 特别是,当它是这样的:

to_exp([*,[+,a,1],[-,3,b]]).

甚至更糟:

to_exp([*,[+,[*,4,2],1],[-,3,b]]).

我的意思是,如果外部列表的元素是列表,我不知道如何确定它是三个元素的列表,其中每个元素都是一个原子/数字。 有小费吗?:)

编辑2

好吧,有人告诉我它变得太复杂了。 也许吧,但我是 Prolog 的新手,我只使用到目前为止我学到的工具/技术,因为我应该做的任务是这样构建的。 当然,肯定有更简单的方法,就像@mat 建议的那样,但到目前为止我还没有了解difmaplist谓词。 这就是为什么我决定以这种方式继续这个。

我发现不需要分别检查atomnumber 如果术语是数字、原子或空列表,则atomic/1会返回 true(因此@mat 提到的关于 SWI-Prolog 的问题似乎没有那么重要)。 之后,我更改了以前的谓词,并将to_exp完成为:

subst(T,A,V,R):-T=..L,make_simple(L,L1),replace(L1,A,V,L2),to_exp(L2,R).

make_simple([],[]).
make_simple([H|T],[H|W]):-atomic(H),make_simple(T,W),!.
make_simple([H|T],[W1|W2]):- \+atomic(H),H=..H1,make_simple(H1,W1),make_simple(T,W2),!.

replace([],_,_,[]).
replace([A|T],A,V,[V|W]):- replace(T,A,V,W),!.
replace([H|T],A,V,[H|W]):- H\=A,\+is_list(H),replace(T,A,V,W),!.
replace([H|T],A,V,[W1|W2]):-H\=A, is_list(H),replace(H,A,V,W1),replace(T,A,V,W2),!.

to_exp([],[]).
to_exp([Z,H1,H2],L):-atomic(H1),atomic(H2),L=..[Z,H1,H2],!.
to_exp([Z,H1,H2],L):- \+atomic(H1),atomic(H2),to_exp(H1,W1),L=..[Z,W1,H2].
to_exp([Z,H1,H2],L):- atomic(H1),\+atomic(H2),to_exp(H2,W1),L=..[Z,H1,W1].
to_exp([Z,H1,H2],L):- \+atomic(H1),\+atomic(H2),to_exp(H1,W1),to_exp(H2,W2),L=..[Z,W1,W2].

现在,它适用于函子和参数,简单的和嵌套的。 无论如何,感谢您的影响,我以后肯定会考虑使用difmaplist 干杯:)

请考虑 Prolog 术语的完整规律性。

substitution(A0, A0, A, A).    
substitution(T0, A0, A, T) :-
        dif(T0, A0),
        T0 =.. [F|Args0],
        maplist(subst_(A0, A), Args0, Args),
        T =.. [F|Args].

subst_(A0, A, T0, T) :- substitution(T0, A0, A, T).

示例查询及其结果:

?- substitution(a+b+[c,d,a], a, 2, R).
R = 2+b+[c, d, 2] ;
false.

尽管如此,这个问题有更有效的答案,我会为那些像我这样的 Prolog 初学者发布这个答案,因为它使用的是非常基本的操作:

subst(T,A,V,R):-T=..L,make_simple(L,L1),replace(L1,A,V,L2),to_exp(L2,R).

make_simple([],[]).
make_simple([H|T],[H|W]):-atomic(H),make_simple(T,W),!.
make_simple([H|T],[W1|W2]):- \+atomic(H),H=..H1,make_simple(H1,W1),make_simple(T,W2),!.

replace([],_,_,[]).
replace([A|T],A,V,[V|W]):- replace(T,A,V,W),!.
replace([H|T],A,V,[H|W]):- H\=A,\+is_list(H),replace(T,A,V,W),!.
replace([H|T],A,V,[W1|W2]):-H\=A, is_list(H),replace(H,A,V,W1),replace(T,A,V,W2),!.

to_exp([],[]).
to_exp([Z,H1,H2],L):-atomic(H1),atomic(H2),L=..[Z,H1,H2],!.
to_exp([Z,H1,H2],L):- \+atomic(H1),atomic(H2),to_exp(H1,W1),L=..[Z,W1,H2].
to_exp([Z,H1,H2],L):- atomic(H1),\+atomic(H2),to_exp(H2,W1),L=..[Z,H1,W1].
to_exp([Z,H1,H2],L):- \+atomic(H1),\+atomic(H2),to_exp(H1,W1),to_exp(H2,W2),L=..[Z,W1,W2].

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM