【发布时间】:2017-05-14 11:50:04
【问题描述】:
所以我有这种数学语言,它是这样的:
E -> number
[+,E,E,E] //e.g. [+,1,2,3] is 1+2+3 %we can put 2 to infinite Es here.
[-,E,E,E] //e.g. [-,1,2,3] is 1-2-3 %we can put 2 to infinite Es here.
[*,E,E,E] //e.g. [*,1,2,3] is 1*2*3 %we can put 2 to infinite Es here.
[^,E,E] //e.g. [^,2,3] is 2^3
[sin,E] //e.g. [sin,0] is sin 0
[cos,E] //e.g. [cos,0] is cos 0
并且我想编写一组规则,以在 prolog 中找到由该语言编写的数学表达式的数值。
我首先编写了一个名为“check”的函数,它根据我们拥有的语言检查列表是否以正确的方式编写:
check1([]).
check1([L|Ls]):- number(L),check1(Ls).
check([L|Ls]):-atom(L),check1(Ls).
现在我需要编写函数“evaluate”,该函数接受一个列表,该列表是该语言编写的表达式,以及一个变量,该变量是与该语言对应的数值。 示例:
?-evaluate([*,1,[^,2,2],[*,2,[+,[sin,0],5]]]],N) -> N = 40
所以我写了这个:
sum([],0).
sum([L|Ls],N):- not(is_list(L)),sum(Ls,No),N is No + L.
min([],0).
min([L|Ls],N):-not(is_list(L)), min(Ls,No),N is No - L.
pro([],0).
pro([X],[X]).
pro([L|Ls],N):-not(is_list(L)), pro(Ls,No), N is No * L.
pow([L|Ls],N):-not(is_list(L)), N is L ^ Ls.
sin_(L,N):-not(is_list(L)), N is sin(L).
cos_(L,N):-not(is_list(L)), N is cos(L).
d([],0).
d([L|Ls],N):- L == '+' ,sum(Ls,N);
L == '-',min(Ls,N);
L == '*',pro(Ls,N);
L == '^',pow(Ls,N);
L == 'sin',sin_(Ls,N);
L == 'cos',cos_(Ls,N).
evaluate([],0).
evaluate([L|Ls],N):-
is_list(L) , check(L) , d(L,N),L is N,evaluate(Ls,N);
is_list(L), not(check(L)) , evaluate(Ls,N);
not(is_list(L)),not(is_list(Ls)),check([L|Ls]),d([L|Ls],N),
L is N,evaluate(Ls,N);
is_list(Ls),evaluate(Ls,N).
它只适用于一个列表并返回正确答案,但不适用于主列表中的多个列表,我的代码应该如何?
【问题讨论】:
-
如果
check(L)在列表中失败,整个谓词不应该简单地失败而不是尝试评估无效列表吗?并且not(is_list(Ls))可能在语义上不合理,因为在这种情况下,列表的尾部(在这种情况下为Ls)预计始终是一个列表。 -
我不会以这种方式组织程序,但鉴于您的方法,您需要做的是让每个运算符谓词在调用
d/2时递归并随时调用d/2它遇到一个子列表(您目前只允许not(is_list(L)))。
标签: prolog