user502187
user502187

Reputation:

Can single sided unification improve error handling?

Inspired by this question, I am trying to harden error
handling of reverse/2. So I tried this implementation:

reverse(X, Y) :- reverse(X, [], Y).

reverse(X, _, _) :- var(X), throw(error(instantiation_error,_)).
reverse([], X, R) :- !, R = X.
reverse([X|Y], Z, R) :- !, reverse(Y, [X|Z], R).
reverse(X, _, _) :- throw(error(type_error(list,X),_)).

Everything works fine, until I try reverse/2 as a generator:

?- reverse([1,2,3],X).
X = [3, 2, 1].

?- reverse(2,X).
ERROR: Type error: `list' expected, found `2' (an integer)

?- reverse(X,Y).
ERROR: Arguments are not sufficiently instantiated

Can single sided unification change the situation, some typical solution based on single sided unification so that the generator reverse(X,Y) would still work? Single sided unification is available in SWI-Prolog 8.3.19.

Upvotes: 0

Views: 90

Answers (2)

Peter Ludemann
Peter Ludemann

Reputation: 1005

This seems to work (a straightforward translation to use => of reverse/2 in library(lists)):

reverse(List, Reversed) =>
    reverse(List, [], Reversed, Reversed).

reverse([], Ys, Reversed, Tail) =>
    Reversed = Ys,
    Tail = [].
reverse([X|Xs], Rs, Reversed, Tail) =>
    Tail = [_|Bound],
    reverse(Xs, [X|Rs], Reversed, Bound).

Upvotes: 0

user502187
user502187

Reputation:

I am afraid I cannot present a single sided unification solution. Its rather that normal unification in the form of (\=)/2 could be useful. I hardly use (\=)/2 ever. The solution is inspired by Dijkstra guards if-fi, link to paper at end of this post:

if
Cond1 -> ActionList1
..
Condn -> ActionList2
fi

The if-fi aborts if none of the conditions Cond1,..,Condn is satisfied. So we simply use a conjunction of the negation of the conditions:

reverse(X, Y) :- reverse(X, [], Y).

reverse(X, _, _) :- X \= [], X \= [_|_], throw(error(type_error(list,X),_)).
reverse([], X, R) :- R = X.
reverse([X|Y], Z, R) :- reverse(Y, [X|Z], R). 

Seems to work:

?- reverse([1,2,3],X).
X = [3, 2, 1].

?- reverse(2,X).
ERROR: Type error: `list' expected, found `2' (an integer)

?- reverse(X,Y).
X = Y, Y = [] ;
X = Y, Y = [_1778] ;
X = [_1778, _2648],
Y = [_2648, _1778] ;
Etc..

So single sided unification might be the wrong approach? I dont know. The above solution incures an overhead, unless some indexing might optimize away (\=)/2. Could even work in connection with attributed variables.

Nondeterminacy and Formal Derivation of Programs
Edsger W. Dijkstra - Burroughs Corporation
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.90.97&rep=rep1&type=pdf

Upvotes: 1

Related Questions