It took me a while to resolve my timidity and start this email. It's about a more or less different approach to designing a syntax for rules. One guideline was to avoid a mutitude of syntactic constructs - I tried to get by with a minimum of phrases. Some requirements I kept in mind: * It must be possible to dynamically permit and forbid CE joining by conditional expressions. * It must be possible to continue CE joining via more than one way over the CEs present in a single LHS. * CE joining may terminate, and lead to an activation, at more than one point in the the several ways over the CEs of a single LHS, where each termination has its own consequence. As I understand the LHS part of a rule, it's about computing one or more Booleans guarding the execution of RHS code, more than one Boolean for a more sophisticated structure, with RHS code being in more than one place. In addition to determining these Booleans it must also be possible to pick up (i.e., bind a variable to) participating objects, their fields and "ad-hoc" results. Basically there are several kinds of value producing elements (VPEs): Patterns, Accumulators, Evaluations. And then there are "outer level" Operators (OLOs) for combining these elements. One guideline in the syntax design is to distinguish between OLOs and producing elements. Hence, the OLOs are ['when'|'and'] Block 'or' Block 'xor' Block In addition to the RHS 'then' Block all Blocks have the same enclosing pair of braces ({...}) and contain a sequence of VPEs or OLOs and RHSs. There is a simple VPE producing a Boolean: 'is' '(' BooleanExpression ')' Patterns combine a type and a parenthesized sequence of (optional) positional bindings and (optional) constraints. (Nothing new here.) Rules may contain repeated alternations of an OLO and a "then" block, and such blocks may be placed after any VPE. (This means that 'nand' and 'nor' blocks might be useful, too - if only to detect where a match fails.) rule ex1 when { $p: Person( name == "Joe" ) } then { System.out.print( $p ); } xor { $c: Car( owner == $p ) then { System.out.println( " owns " + $c ); } is() then { System.out.println( " has no car" ); } // is() == true } and { Person( $name: name, spouse == $p ) } then { System.out.println( "Is married to " + $name ); } A variable bound to an object can be used to force identity in a subsequent pattern, possibly combined with a subclass test. If given with no type, it just recalls the bound object. If followed by a pipe, it constructs a "local fact". (Hitherto: from.) rule ex2 when { $p: Person( name == "Joe", $a: address ) or { $p: Teacher( subjects contains Subject.MATH ) then { System.out.println( "Joe teaches MATH" ); } $p: Student( subjects contains Subject.MATH ) then { System.out.println( "Joe learns MATH" ); } $p ( $occ: occupation != null ) then { // "no type" is "type when bound" System.out.println( "Joe is a " + $occ ); } is( $p.age > 16 ) then { System.out.println( "Joe is an idle loafer!" ); } } and { $a | Address( state == "CA" ) } then { System.out.println( "Lives in California!" ); } Any block may be preceded by a VPE, which acts as a guard, i.e., the block is entered only when there is a match to a fact or a true result. The VPE 'let' evaluates and returns any expression; it's truth value being true by definition. It makes only sense when combined with a bound variable. If the expression returns a collection, it succeeds repeatedly (or-ish). rule ex3 { // note that 'and'/'when' can be omitted $subject: let( EnumSet.allOf( Subject.class ) ) accumulate( $t: Teacher( subjects contains $subject ); $teachers: asList( $t.name ); $c > 0 ) } then { System.out.println( "Subject " + $subject + " taught by " + $teachers ); } You may hove noticed that the patterns x{...} and y(...) are used for separate syntactic categories. This improves "orientation quality" in the code. Another example: rule ex11 when { $car: Car( $owner: owner ) } then { System.out.print( $car ); } or { Person( this == $owner ) then { System.out.print( " owned by " + $owner ); } not Person( this == $owner ) then { System.out.print( " ownerless" ); } } then { System.out.println(); // just a LF } when { $tv: TrafficViolation( car == $car ) } then { System.out.println( "traffic violation " + $tv ); } A multiway continuation with the first matching branch is written using "xor". rule ex12 when { $p: Person() Car( owner == $p ) xor { { $p( name == "John" ) $b: let( new B(1) ) } { $p: Worker( name == "john" ) $b: let( new B(2) ) } { $b: let ( new B(3) ) } } A( field == $b ) } then { } Since not() and exists() result in a Boolean value, it should be possible to bind a variable to the result, and to use them inside is(). rule ex21 when { $ex: is( not Bus( colour == Colour.RED ) ) } then { System.out.println( "There are " + ($ex ? "" : "no ") + "red busses." ); }