All facts use an underlying deftemplate, but for ordered facts the
deftemplate is automatically created for you with a single multifield
slot to contain all of the values. The parser for the fact query
functions use the deftemplate to determine the list of slots which can
be referenced within its body, so you'll get an error if it's not
defined. In the example where you used (assert (x)), the assertion
automatically created the deftemplate before the fact was asserted, so
the subsequent any-factp had a deftemplate available. My
recommendation would be to use deftemplates, but what you can do to
get this to work is to use the eval function to allow you to defer the
parsing of the any-factp expression until after you've determined that
the deftemplate exists:
CLIPS> (and (member$ y (get-deftemplate-list)) (eval "(any-factp ((?f
y)) TRUE)"))
FALSE
CLIPS> (assert (y))
<Fact-1>
CLIPS> (and (member$ y (get-deftemplate-list)) (eval "(any-factp ((?f
y)) TRUE)"))
TRUE
CLIPS>
So if the deftemplate doesn't exists, there can't be any facts with
that relation name, otherwise at some point the fact existed, so parse
and execute the any-factp function to determine if it stil exists.