Help with goal_expansion

I want to be able to write

Remainder = List -- Item

and have it mean

select(Item, List, Remainder)

I’ve tried with various versions of the following, but it never works.

:- op(600, xfx, '--' ).

        (Remainder = List -- Item),
        (select(Item, List, Remainder))

With the above, I’m told:

ERROR: Goal expansion bound a variable to _5540--_5562

?- [user].
|: :-op(600, xfx, '--').
|: goal_expansion(
|: (Remainder = List -- Item),
|: (select(Item, List, Remainder))
|: ).
|: ^D% user://1 compiled 0.01 sec, 1 clauses

?- Remainder = [a, s, d] -- s.
Remainder = [a, d] ;


For me it worked actually. And I post it here with a certain happiness, because it was one of the few times things worked…without issuing any warnings, error messages, strange non-existent modules, dependencies, certificates and so on

Yes. It does work.

There is something else in the file (which works) but the two seem to cause problems together.

I also have some DCG stuff in the file, and had

... --> [] | [_] , ... .

The two together break things.

1 Like

The problem is that goal_expansion/2 uses normal unification. So, if it encounters the goal A = B, this also unifies. That is where the warning is about. So, you need something like this:

goal_expansion(Remainder = Select, Goal) :-
     Select = (List -- Item),
     Goal = select(Item, List, Remainder).

P.s. op(600, xfx, '--' ). can simply be op(600, xfx, -- ).. Being an operator or not does not imply whether or not quotes are required. Besides the usual atoms of letters, sequences of graph characters also make up an atom without the need for quotes.


By the way, thanks for letting me discover this predicate select/3 which I didn’t know about… similar to member/2 in some way but with a further argument position. You can use it as member/2 if you use an anonymous variable, but it doesn’t make much sense of course