Build math & comparision functions.

This commit is contained in:
Simon Forman 2019-08-11 17:48:29 -07:00
parent ab454375c0
commit cd60816429
3 changed files with 119 additions and 0 deletions

View File

@ -10,3 +10,8 @@ defs.pl: meta-defs.pl parser.pl defs.txt thun.pl
--consult-file thun.pl \
--query-goal do
math.pl: meta-math.pl
gprolog \
--consult-file meta-math.pl \
--query-goal do

44
thun/gnu-prolog/math.pl Normal file
View File

@ -0,0 +1,44 @@
func(+, [A, B|C], [D|C]) :-
E =.. [+, B, A],
catch(D is E, _, D = E).
func(-, [A, B|C], [D|C]) :-
E =.. [-, B, A],
catch(D is E, _, D = E).
func(*, [A, B|C], [D|C]) :-
E =.. [*, B, A],
catch(D is E, _, D = E).
func(/, [A, B|C], [D|C]) :-
E =.. [/, B, A],
catch(D is E, _, D = E).
func(mod, [A, B|C], [D|C]) :-
E =.. [mod, B, A],
catch(D is E, _, D = E).
func(>, [A, B|C], [D|C]) :-
E =.. [>, B, A],
catch((E -> D = true ; D = false), _, D = E).
func(<, [A, B|C], [D|C]) :-
E =.. [<, B, A],
catch((E -> D = true ; D = false), _, D = E).
func(>=, [A, B|C], [D|C]) :-
E =.. [>=, B, A],
catch((E -> D = true ; D = false), _, D = E).
func(<=, [A, B|C], [D|C]) :-
E =.. [=<, B, A],
catch((E -> D = true ; D = false), _, D = E).
func(=, [A, B|C], [D|C]) :-
E =.. [=:=, B, A],
catch((E -> D = true ; D = false), _, D = E).
func(<>, [A, B|C], [D|C]) :-
E =.. [=\=, B, A],
catch((E -> D = true ; D = false), _, D = E).

View File

@ -0,0 +1,70 @@
/*
To handle comparision operators the possibility of exceptions due to
insufficiently instantiated arguments must be handled. First try to make
the comparison and set the result to a Boolean atom. If an exception
happens just leave the comparison expression as the result and some other
function or combinator will deal with it. Example:
func(>, [A, B|S], [C|S]) :- catch(
(B > A -> C=true ; C=false),
_,
C=(B>A) % in case of error.
).
To save on conceptual overhead I've defined a term_expansion/2 that sets
up the func/3 for each op.
*/
term_expansion(comparison_operator(X), (func(X, [A, B|S], [C|S]) :-
F =.. [X, B, A], catch((F -> C=true ; C=false), _, C=F))).
% I don't use Prolog-compatible op symbols in all cases.
term_expansion(comparison_operator(X, Y), (func(X, [A, B|S], [C|S]) :-
F =.. [Y, B, A], catch((F -> C=true ; C=false), _, C=F))).
% Likewise for math operators, try to evaluate, otherwise use the
% symbolic form.
term_expansion(math_operator(X), (func(X, [A, B|S], [C|S]) :-
F =.. [X, B, A], catch(C is F, _, C=F))).
term_expansion(math_operator(X, Y), (func(X, [A, B|S], [C|S]) :-
F =.. [Y, B, A], catch(C is F, _, C=F))).
% Symbolic math. Compute the answer, or derivative, or whatever, later.
math_operator(+).
math_operator(-).
math_operator(*).
math_operator(/).
math_operator(mod).
comparison_operator(>).
comparison_operator(<).
comparison_operator(>=).
comparison_operator(<=, =<).
comparison_operator(=, =:=).
comparison_operator(<>, =\=).
expand_op(Op, Term) :- Op, expand_term(Op, Term).
print_o(Stream, Op) :-
findall(Term, expand_op(Op, Term), List),
maplist(writeln(Stream), List).
writeln(Stream, Thing) :-
portray_clause(Stream, Thing),
nl(Stream).
do :-
open(`math.pl`, write, Stream),
print_o(Stream, math_operator(Op)),
print_o(Stream, comparison_operator(Op)),
print_o(Stream, comparison_operator(Op, Po)),
close(Stream),
halt.