BackwardChaining

Version 3

    Facts and Simple querries with ordered facts

    assert an ordered fact
    assert( person( "mark", "UK" ) )
    

    return a list of one

    list = person("mark", "UK")
    
    assert another fact
    assert( person( "mic", "UK" ) )
    

     

    Returns a list of two, as $name is not bound

    list = person( $name, "UK )
    

     

    returns a list of 1, as $name is now bound

    $name == "mark
    list = person( $name, "UK )
    

     

    Compound querries with ordered facts

    assert( likes( "mark", "beans" )
    assert( likes( "mark", "pizza" )
    assert( likes( "mark", "coke" )
    assert( likes( "mic", "meat" )
    assert( likes( "mic", "pizza" )
    assert( likes( "mic", "fish" )
    

     

    inline query, returns a  list of 1, mic

    list = person( $name, "UK ), likes( $name, "meat" )
    

     

    The "likes" query acts as a correlated subquery, it is evaluated for each returned "person" row, $name handles the correlation.

     

    Lets turn this into a  named query - see its just like an existing drools query, except it takes a parameter:

    query "who likes meat"($name)
        person( $name, "UK" )
        likes(  $name, meat )
    end
    

     

    We can use the above query in two ways

    returns  a  list of  1

    list = "who likes meat"( "mic" )
    

    returns an empty list

    list = "who likes meat"( "mark" )
    

    Also returns a list of 1, as $name is  not yet bound

    list = "who likes meat"( $name )
    

     

    Returns an empty list, as $name is  now bound

    $name = "mark"
    list = "who likes meat"( $name )
    

     

    Nested Querries

    so we can create "views" on compound querries.

    query "favourite foods"($name, $location, $food )
        person( $name, $location )
        likes(  $name, $food )
    end
    
    assert( restaurant("meat hut", "UK", "meat") )
    assert( restaurant("meat hut", "USA", "meat") )
    assert( restaurant("pizza hut", "UK", "pizza") )
    
    
    query "my restaurants"($personName, $restuarantName, $food)
       "favourite foods"($personName, $food, $location)
       restaurant($restaurantName, $location, $food)
    end
    

     

    If no variables are needed for a correlated query you can just use a

    "my restaurants"("mic", *, *)   
    

    returns a list of

    "mic", "meat hut", "meat"
    "mic", "pizza  hut", "pizza"
    

     

    Querries with rules

    So how does this work with rules?

    rule  "when hungry
        when
             Person( $name : name; hungry == true )
             "my restaurants"( $name, $restuarantName, $food ) //notice $food and $location where not previous  bound         
        then
           send $name to $restuarantName to eat $food
    end       
    

     

    language changes to facilite prolog style usage of rules

    'from' is ideal for iterating over collections return 'from' a function call. And ofcourse we turn function calls that return single values into a collection to do an iteration of one. However I thought it might be more declarative to add an = or an 'is' keyword.

     

    $f = $dog.name

    or possible

    $f is $dog.name

    but I think I prefer  the first

     

    Internally this would just use 'from', but it might be more declaratively understandable to allow the above. The other reason is it facilitates prolog style backward chaining, where you can use something like this in a rule:

    c_to_f(C,F) :-

       F is C  9 / 5 + 32.

     

    C is an 'in' variable and F is an 'out' variable.

     

    Further to this I thought it would be good to allow function calls, that are basically converted to evals

    log($fact)

    instead of

    eval( log($fact) )