Using `expand_answer` in a package

I would like to use user:expand_answer from a package to output specific attributed variables in a more user-friendly format at the top level. The issue is that expand_answer takes a list of bindings so any implementation must assume responsibility for mapping the whole binding list. Any failure will backtrack to an alternative definition but that precludes different packages co-operating to generate a final binding list.

I considered using the attr_portray_hook for this but this affects write which I would like to reserve for the transparent (i.e., less friendly) format.

This probably isn’t a common problem. Hooks generally only are applied to a single term,.e.g., portray, or are context sensitive like exception.

One possibility is to introduce a new hook (could use the same name) which maps a single <Name>=<Value> binding and leaving the top level code to handle the list. A package could then provide a definition of the hook which either succeeds, producing the new binding, or fails and backtracks to allow other definitions, or the default, to do the mapping.

Any other ideas?

The standard solution to this is attribute_goals//1.

Not sure how attribute_goals can be used for this. Can you elaborate a bit?

As an aside, I’m not sure how to implement attribute_goals for my application. Each attributed variable is, in effect, a reference for the whole interval constraint network. And this network is a cyclic graph. With some effort it may be possible to “de-compile” this structure to a list of goals, but it’s not clear why this would be useful to anyone.

This hook cooperates with copy_term/3 which is used by the toplevel. The idea is that a term with attributed variables (constraints) can be represented as the same term without and goals that re-establish the constraints. The task of this hook is to look at the attributes and re-create a goal that cleanly reinstates the same or at least a semantically equivalent set of attributes. Thus:

?- dif(x(1,X), x(1,2)).
dif(X, 2).

copy_term/3 not only supports the toplevel, but also code that wants to transfer constraints to another application, wants to generate code from terms that hold constraints, etc.

Thanks. I can almost make this work. My problem is that the top level variables reference internal intervals representing the values of sub-expressions. These are also output causing considerable clutter:

?- X::real(0,10),{X==Y+1,Z>=X-6,V==10.0}.
X::real(0, 10),
_24514::real(0, 10),
Y::real(-1, 9),
_24550::real(-6, 4),
Z::real(-6, 1.0Inf),
V:: 10.00000000000000...,
_24608:: 10.00000000000000... .

For complicated constraints there may be many times more “internal” intervals than “top level” intervals. I might be able to flag those, but I’m not sure if I can prevent them from being output at the top level. So I need to look deeper.