私は述語invert(X, Y)
を書きたいと思っています。Y
X
+
-
例えば
?- invert(2 + 3, 2 - 3).
yes.
例えば
?- invert(3 + (2 + 4), X).
X = 3 - (2 - 4).
univ を使用して式の項を検査し、演算子を演算子に=..
置き換えることができます。+/2
-/2
invert(Left+Right, ILeft-IRight):-
!,
invert(Left, ILeft),
invert(Right, IRight).
invert(Exp, IExp):-
Exp=..[Functor|Args],
findall(NArg,
( member(Arg, Args),
invert(Arg, NArg)
), NArgs),
IExp=..[Functor|NArgs].
最初の節は主関手 + を伴う項を扱います。2 番目の節は、主関手が異なる項に適用されます。
[編集] コメントの 1 つが示唆するように、最初の句を変更して、両方の引数invert/2
がインスタンス化されていない場合に無限ループを回避することができます。この句に置き換えるだけです。
invert(Exp, ILeft-IRight):-
Exp=..[+, Left, Right],
!,
invert(Left, ILeft),
invert(Right, IRight).
もっと簡単なことをお勧めします:
invert(P,P):-atomic(P). % P is konstant, e.g. invert(3,3)->true
invert(T-P,T1-P1):-invert(P,P1),invert(T,T1).
invert(T+P,T1-P1):-invert(P,P1),invert(T,T1).