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).
Example - Numerical formula
(use-modules (opencog)) (use-modules (opencog exec)) ; Compute TV = (1-sA*sB, cA*cB) (DefineLink (DefinedPredicate "my formula (1-sA*sB, cA*cB)") (PredicateFormula (Minus (Number 1) (Times (StrengthOf (Variable "$X")) (StrengthOf (Variable "$Y")))) (Times (ConfidenceOf (Variable "$X")) (ConfidenceOf (Variable "$Y"))))
The fully-worked example can be found in /examples/atomspace/formulas.scm tutorial.
Example - Recursive function
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 (DefinedPredicate "loopy") (SatisfactionLink (SequentialAnd (EvaluationLink (GroundedPredicate "scm:prt") (ListLink)) (DefinedPredicate "loopy") ))) ; Run the above. (cog-evaluate! (DefinedPredicate "loopy"))
The above example should print
scheme@(guile-user)> (cog-evaluate! (DefinedPredicate "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 SatisfactionLink has no variables in it. In the general case, the tail call optimization cannot be performed.