Current_arithmetic_function/1 - Ever wanted to check if something is an arithmetic function?


?- X is abs(sin(5)).
X = 0.9589242746631385.
?- current_arithmetic_function(abs(sin(X))).

Ref: Arithmetic Functions

?- current_arithmetic_function(Head),numbervars(Head).
Head = abs(A) ;
Head = acos(A) ;
Head = acosh(A) ;
Head = A/\B ;
Head = asin(A) ;
Head = asinh(A) ;
Head = atan(A) ;
Head = atan(A, B) ;
Head = atanh(A) ;
Head = atan2(A, B) ;
Head = \A ;
Head = A\/B ;
Head = ceil(A) ;

As a portability person, I have to point out that current_arithmetic_function/1 is SWI-specific and not supported by any other Prolog system that I know of. As such, it isn’t useful when you’re writing code for multiple systems and want to check if an arithmetic function is supported by the current system. On non-SWI systems, the only way to check if an arithmetic function exists is to try calling it and check if it throws an error or not.

You can define a helper predicate like this that checks if an arithmetic function exists. This will use current_arithmetic_function/1 if possible and fall back to catch/3 otherwise. (Although for this use case current_arithmetic_function/1 doesn’t offer that much benefit, so it may be simpler to just always use the catch/3-based solution.)

:- if(predicate_property(current_arithmetic_function(_), _)).
% Use current_arithmetic_function/1 if possible (supported by SWI).
check_arithmetic_function(FuncCall) :-
:- else.
% Otherwise try to call the function and see if it works or not.
check_arithmetic_function(FuncCall) :-
    catch(_Res is FuncCall, _Error, false).
:- endif.

Example usage:

?- check_arithmetic_function(log(2, 4)).
?- check_arithmetic_function(ceil(1.5)).
% SICStus
| ?- check_arithmetic_function(log(2, 4)).
| ?- check_arithmetic_function(ceil(1.5)).

Might be wise to check the error. Should be error(type_error(evaluable, Name/Arity), _). It still isn’t satisfactory though. For example code analysis cannot easily use this as it doesn’t have concrete values for the arguments and there is no easy way to know what arguments are valid for a function. current_arithmetic_function/1 (or something similar) should have been in the ISO core standard …

1 Like