Append solution using pure production rules

This is a follow up to last week's email thread where Hassan issued a 
challenge to write production rules to perform append, presumably 
restricted to assert actions and the following operations on sequences 
(or lists): first, rest, cons, isEmpty, and isEqual.

First is a terse solution in an ad hoc language:

	appendArgs([],R) -> appendResult([], R, R)
	appendArgs([H|T], R) -> appendArgs(T, R)
	appendArgs([H|T], X), appendResult(T, X) -> appendResult([H|T], X, [H|R])

To perform an append, assert an appendArgs fact, e.g.

	appendArgs([a b c], [d e]).

The result is contained in an appendResult fact, e.g.

	appendResult([a b c], [d e], [a b c d e])

I have tested this using Oracle's ascii java-like production rule language, which I've attached.
/*
	This is a sample program written in Oracle's java-like rule language (RL).

	This sample uses Rules to append 2 lists.  
	We use java.util.List, but we use only get(0),
	isEmpty(), add(0), and subList(1, size()) methods.

	We define RL functions to look "lispy" that encapsulate the List methods.
	This doubles as a use-case for user defined functions in RIF, by the way.
*/
import java.util.*;

function cons(Object first, List rest) returns List {  	
	List ret = new ArrayList(rest);
	ret.add(0, first);  
	return ret;
}

function isEmpty(List list) returns boolean {
	return list.isEmpty();
}

function isEqual(List list1, List list2) returns boolean {
	return list1.equals(list2);
}

function first(List list) returns Object {
	return list.get(0);
}

function rest(List list) returns List {
	return list.subList(1, list.size());
}

class AppendArgs {
	List left;
	List right;
}

class AppendResult {
	List left;
	List right;
	List result;
}


rule push {
	if fact AppendArgs a && !isEmpty(a.left) {
		assert(new AppendArgs(left: rest(a.left), right: a.right));
	}
}

rule base {
	if fact AppendArgs a && isEmpty(a.left) {
		assert (new AppendResult(left: a.left, right: a.right, result: a.right));
	}
}

rule pop {
	if fact AppendArgs a && !isEmpty(a.left) && fact AppendResult r && 
		isEqual(rest(a.left), r.left) && isEqual(a.right, r.right) {
		assert(new AppendResult(
			left: a.left, right: a.right, 
			result: cons(first(a.left), r.result)));
	}
}

final List left  = Arrays.asList(new String[]{"a", "b", "c"});
final List right = Arrays.asList(new String[]{"d", "e"});

assert(new AppendArgs(left: left, right: right));  

rule printResult {
	if fact AppendResult r && isEqual(r.left, left) && isEqual(r.right, right) {
		println(r.result);
	}
}

run();

//prints: [a, b, c, d, e]

Received on Thursday, 16 March 2006 17:53:15 UTC