问题
How can I add a function (e.g., hammingweight) and use it in expressions occuring in the right-hand side is some (is)/2
goal?
Could something like goal_expansion or term_expansion help here?
I acknowledge that this is not a big feature, but it could increase readability of some of my Prolog programs.
Writing a custom (is)/2
predicate (implementing a custom expression evaluator) is do-able, but I would like to keep runtime overhead low, as I don't want to sacrifice readability for runtime overhead in this case.
回答1:
There is no such provision in ISO Prolog, neither to extend (is)/2
nor to rely on goal expansion. And, looking at the various implementation specific features that are offered by some implementations to this end, there is no generally agreed upon way to do this. So implementing your own (my_is)/2
seems to be the best way to go.
Also note, that this would not only affect (is)/2
but also all other built-ins that use evaluable functors. In particular, all arithmetic comparison built-ins (8.7 Arithmetic comparison) (see this overview) would be affected.
回答2:
My simple minded (~20 LOC) syntax sugar, lifter, it's based on goal_expansion.
With lifter, the clause
longer(A,B) :-
length(A,º) > length(B,º).
is expanded to
longer(A, B) :-
length(A, C),
length(B, D),
C > D.
回答3:
You can use Logtalk's term-expansion mechanism, which is portable and works with its twelve supported Prolog compilers (*). Logtalk compiling and loading and loading predicates accept Prolog files and will output the corresponding Prolog expanded files. For example, assuming that the file you want to expand is named source.pl
and that your term_expansion/2
and goal_expansion/2
predicate definitions are in a file named expansions.pl
, you can do something like:
% first, load the expansion hooks:
| ?- [expansions].
...
% second, expand a file using those hooks:
| ?- logtalk_compile(source, [hook(user)]).
...
You will get the expanded file, which will be (by default) named source_pl.pl
(in a directory that will depend on the value of the scratch_directory
Logtalk flag). If the expansions are contained in a Prolog module, use above the module name instead of user
. If the source.pl
file contains a module instead of plain Prolog code, you'll need to define some clauses for the term_expansion/2
predicate to avoid Logtalk compiling the module as an object. But in the simpler case where you're not using modules, the two queries above should suffice.
One feature of Logtalk's term-expansion mechanism that might be useful is that you can mark a term or a goal to not be expanded or further expanded by wrapping it with the {}/1
control construct.
(*) Note that term-expansion mechanism are not standard, not provided by all Prolog implementations, and with significant differences between implementations.
来源:https://stackoverflow.com/questions/28854812/implementing-user-defined-arithmetic-functions