<< Previous exercise (4.70) | Index | Next exercise (4.72) >>


 This will postpone some infinite loop. for example: 
 (assert! (married Minnie Mickey)) 
 (assert! (rule (married ?x ?y) 
                (married ?y ?x))) 
 (married Mickey ?who) 
 if we don't use delay, there is no answer to display. but if we use it, we can get: 
 ;;; Query output: 
 (married Mickey Minnie) 
 (married Mickey Minnie) 
 (married Mickey Minnie) 
 this is better than nothing. the reason of this difference is that in this example (apply-rules query-pattern frame) will lead to infinite loop, if we delay it, we still can get some meaningful answers. 

As a supplement to the solution of meteorgan, the lazy evaluation here can actually avoid infinite loops in some situations. Specifically, when using filters, we don't actually use the actual result of a query, since we only care about whether the result's empty or not. Consider the following example:

 (rule (son ?x ?y) 
       (son ?x ?y)) 

We accidentally define a rule that shares the same name with the assertions. The query (son ?x ?y) is supposed to find all the assertions before get stuck in an infinite loop. But the query (not (son ?x ?y)) can avoid the infinite loop thanks to lazy evaluation.

The example above illustrates a very extreme situation, where a query takes an infinite amount of time. Even if queries do terminate, lazy evaluation can still save a lot of computation. Consider the following example:

 (not (or <subquery#0> 

Any subquery with non-empty result can save the effort of processing rest of the subqueries.