I tried to use the library arithmetic_types which does compile time expansion of user defined arithmetic predicates with dicts but it doesn’t work.
Basically, compile time expansion of dicts apply earlier than arithmetic_types, which blocks arithmetic_types to do its own compile time expansion.
:- use_module(library(arithmetic_types)).
:- arithmetic_function('.+'/2).
test_pred(Y) :-
X = array{}.arange(10),
Y is (X .+ X).to_list().
And the resulting program:
?- listing(test_pred).
array:test_pred(Y) :-
'.'(array{}, arange(10), A),
X=A,
'.'(X.+X, to_list(), B), % X .+ X should have expanded into its own goal
Y is B.
I answered this on the referenced GitHub issue, but in case there’s a wider community of interest:
library(arithmetic) uses goal expansion to support user defined arithmetic functions. In general terms it lifts any user defined functions out of the is (or related arithmetic comparisons) but leaves things it deems “evaluable”, like numbers, character codes, etc. alone. The ‘.’ functional notation is deemed evaluable, so no further internal expansion of any arguments is done. The entire ‘.’ sub-expression is actually lifted and expanded by the dictionary support code, which explains the actual code listed after expansion. At least, that’s my understanding.
The goal expansion of is still has to test for ‘.’ even though it may not be present in the source expression. The overflow occurs because the original clause you commented out prevented reaching a subsequent clause with an unexpected argument type, and I should close that loophole.
Of course you’re free to modify the code but you should be prepared to debug the result.
Ah, thank you.
I didn’t know if I was hitting a bug in arithmetic_types or if it was by design.
I’ll try to experiment on my side to see if I can correctly integrate dict functional notation with arithmetic_types.
If I manage to find something useable, I will let you know.