A DefinedPredicateNode is a kind of PredicateNode that may be defined with the DefineLink. The sole reason for having this node type is to be able to instantly recognize when a defined node is being used (as otherwise, every atom would need to be looked up to see if it has an associated definition).
The following shows how a DefinedPredicateNode can be used to create a recursive function:
(use-modules (opencog)) (use-modules (opencog exec)) ; Increment, print, sleep. After the 6th call, return false; else return true. (define n 0) (define (prt) (set! n (+ n 1)) (format #t "call count ~a\n" n) (sleep 2) (if (< n 6) (stv 1 1) (stv 0 1))) ; A recursive loop, calls itself forever as long as prt returns 'true' (DefineLink (DefinedPredicateNode "loopy") (SatisfactionLink (SequentialAndLink (EvaluationLink (GroundedPredicateNode "scm:prt") (ListLink)) (DefinedPredicateNode "loopy") ))) ; Run the above. (cog-evaluate! (DefinedPredicateNode "loopy"))
The above example should print
scheme@(guile-user)> (cog-evaluate! (DefinedPredicateNode "loopy")) call count 1 call count 2 call count 3 call count 4 call count 5 call count 6 $2 = (stv 0 1) scheme@(guile-user)>
The above is in fact tail-recursive, ad, for this example, the code WILL perform the tail-call optimizaion. However, the optimization can be performed only because this is a very special case: the SatistfactionLink has no variables in it. In the general case, the tail call optimization cannot be performed.