我第一次在prolog工作。 我试图在文本中转换操作。 如, 三+三=六 应该回归真实。 我试过这个。 我在最后一行收到错误,当我尝试添加(ONE,ONE,TWO)时,它返回false而不是true。
numericValue(ONE, 1).
numericValue(TWO, 2).
numericValue(THREE, 3).
numericValue(FOUR, 4).
numericValue(FIVE, 5).
numericValue(SIX, 6).
numericValue(SEVEN, 7).
numericValue(EIGHT, 8).
numericValue(ZERO, 0).
numericValue(NINE, 9).
add(num1,num2,num3):-
numericValue(num1,a),
numericValue(num2,b),
numericValue(num3,c),
(c =:= a+b -> true ; false).
istBiggerThen(XinEng,YinEng) :-
numericValue(XinEng, X),
numericValue(YinEng, Y),
( X < Y -> true ; false).
A + B = C :- add(A,B,C).
最后一行的错误是
ERROR: /home/name/prolog_examples/crypt.pl:24:
No permission to modify static procedure `(=)/2'
答案 0 :(得分:2)
l
次迭代(小写)与V
ariabls(大写):正如@lurker指出的那样,你的原子和变量已经混淆了。所以你的事实应该是这样的:
text_to_number(one, 1).
text_to_number(two, 2).
text_to_number(three, 3).
%% etc...
虽然你的规则需要使用变量,如下所示:
add(A_Text, B_Text, C_Text) :-
text_to_number(A_Text, A_Num),
text_to_number(B_Text, B_Num),
C_Num is A_Num + B_Num,
text_to_number(C_Text, C_Num).
bigger_than(A_Text, B_Text) :-
text_to_number(A_Text, A_Num),
text_to_number(B_Text, B_Num),
A_Num > B_Num.
add(ONE, ONE, TWO)
结果为假的原因是因为add/3
的原始规则只定义了原子num1, num2, num3, a, b, c
之间的关系。当您查询add(ONE, ONE, TWO)
时,Prolog会尝试将变量与规则头部中的原子统一起来,即add(num1, num2, num3)
。因为您有ONE
作为查询的第一个和第二个参数,所以这种统一是不可能的,因为ONE = ONE
只有num1 \= num2
。由于add/3
没有其他规则或事实,查询只返回false
。
子句正文中的语句(即:-
运算符的右侧)被判断为真或假,因此您几乎不需要使用模式(|Condition| -> true ; false)
。例如。如果C_Num is A_Num + B_Num
可以与C_Num
和A_Num
的总和统一,则B_Num
为真,否则为假,在这种情况下,Prolog将开始追踪跟踪。
=:=/2
与is/2
: =:=/2
检查其第一个参数与其第二个参数的值是否相等,该参数可以是可以使用is/2
计算的算术表达式。查询?- X =:= 2 + 2
并且您将获得实例化错误,因为=:=/2
无法将自由变量与数学表达式进行比较。另一方面,is/2
将左侧的变量与右侧表达式的值统一起来:?- X is 2 + 2. X = 4
。
你对=:=/2
的使用会起作用(只要你理顺了变量原子的东西),但你的规则描述了一个低效且迂回的解决方案,原因如下:因为numericValue(Num3,C)
先于算术的评估,Prolog将首先将numericValue(Num3,C)
与第一个合适的事实统一起来,即。 numericValue(one, 1)
然后测试1 =:= A + B
。当失败时,Prolog将与下一个事实numericValue(two, 2)
统一,然后测试2 =:= A + B
,然后测试下一个......直到它最终发生在正确的值上。与我建议的规则相比较:数值A_Num
和B_Num
与C_Num is A_Num + B_Num
相加,将C_Num
与总和统一。然后Prolog将text_to_number(C_Text, C_Num)
与具有C_Num
的适当值的单一拟合事实统一起来。
当术语出现在:-
的右侧或程序的顶层时,正在定义。但是,您不能简单地重新定义谓词(可以这样做,但需要一些簿记和特殊声明。例如,dynamic/1
)。此外,您不希望重新定义+/2
和=/2
等核心术语。但是可以相对轻松地定义自己的谓词。事实上,对谓词定义疯狂是我最喜欢的与Prolog无关的事情之一(尽管我已经注意到在实践中不要使用不必要的运算符,因为它会让你的代码变得晦涩难懂)。
在指令中使用op/3
声明运算符。它具有签名op(+Precedence, +Type, :Name)
(Cf。,SWI-Prolog documentation):
:- op(200, xfx, user:(++)).
:- op(300, yfx, user:(=::=)).
A ++ B =::= C :- add(A, B, C).
行动中:
?- one ++ two =::= X.
X = three.