Module magic?

Library module arithmetic has provides predicate arithmetic_expression_value/2:

?- listing(arithmetic_expression_value).
:- meta_predicate arithmetic:arithmetic_expression_value(:,-).

arithmetic:arithmetic_expression_value(M:Expression, Result) :-
    eval(Expression, M, Result).

true.

?- arithmetic_expression_value(1+1,V).
V = 2.

And I’m wondering by what magic 1+1 unfies with M:Expression.

When a predicate is declared as a meta_predicate with “:” (or 0, 1, 2, etc.) then a call adds the module if it’s not already there. So, your arithmetic_expression_value(1+1, V), when executed, becomes arithmetic_expression_value(user:(1+1), V) (or something like that).

1 Like

Thanks, Peter. That complicates using : as a slice operator, but that’s probably fine as long as it’s only used in a block expression. Currently a naked 2:3 would evaluate to 3 since 2 isn’t a module and 3 is a valid arithmetic value. A workaround is to evaluate _:2:3 which produces the expected value.

To avoid the ambiguity I’d like to perform a quick test to see if M in M:Expression is a module name. The fastest I’ve been able to come up with is:

atom(M), module_property(M,_)

Any other suggestions?

Maybe a better solution is to use a different notation. For example "abcdef"[1..3].

1 Like

Reasonable suggestion. But I would like to maximize notation choices for the user. (This is a check in library(arithmetic).) Even a simple atom check is sufficient for allowing numeric arguments with the : operator.