python-call: returning a list of fact refs

  • Dave

    Dave - 2012-07-12


    I want to return a list of fact references from an external python function that has been called from within a CLIPS function. Basically I pass the python function a list/multifield of fact references and I want to return a subset of these references. However, pyclips doesn't seem to like the list of references that I pass back and I'm  getting the error message:

    File "/usr/local/lib/python2.7/dist-packages/clips/", line 1774, in Call
        return _cl2py(_c.functionCall(func))
    _clips.ClipsError: C14: unsuccessful function call

    The following code snippet highlights my problem:

    import clips
    def pyfunc (facts):
    #    ok
    #    return facts[0]
    #    ok
    #    return [1,2]
    #    causes error
        return [facts[0]]
    clips.Assert("(afact first)")
    clips.Assert("(afact second)")
    (deffunction call-me ()
       (bind ?facts (find-all-facts ((?f afact)) TRUE))
       (printout t "FACTS: " ?facts crlf)
       (bind ?result (python-call pyfunc ?facts))
       (printout t "RESULTS: "  ?result crlf)
       (return TRUE)
    clips_call_me = clips.FindFunction("call-me")
    print clips.StdoutStream.Read()

    As shown from the commented out code, returning a single fact reference is fine, and returning a list of primitive datatypes is fine. However returning a list of fact references fails.

    As far as I can tell this should work as pyclips should convert the list into a mutlfield of facts.

  • Dave

    Dave - 2012-07-12

    Just to add some more information. This looks like it is a bug in the function _py2cl in file This function converts the return python datatype into a clips datatype.  Lines 603 - 633 handle the case for converting lists to multifields:

        elif t1 in (list, tuple):
            li = []
            for x in o:
                t0 = type(x)
                if t0 in (int, long):
                    li.append((_c.INTEGER, int(x)))
                elif t0 == float:
                    li.append((_c.FLOAT, float(x)))
                elif t0 in (str, unicode):
                    li.append((_c.STRING, str(x)))
                elif t0 in (ClipsIntegerType, ClipsFloatType, ClipsStringType,
                            ClipsSymbolType, ClipsInstanceNameType, ClipsNilType):
                elif t0 == Fact:
                    li.append((_c.FACT_ADDRESS, o._Fact__fact))
                elif t0 == Instance:
                    li.append((_c.INSTANCE_ADDRESS, o._Instance__instance))
                elif isinstance(x, int):
                    li.append((_c.INTEGER, int(o)))
                elif isinstance(x, long):
                    li.append((_c.INTEGER, int(o)))
                elif isinstance(x, float):
                    li.append((_c.FLOAT, float(o)))
                elif isinstance(x, str):
                    li.append((_c.STRING, str(o)))
                elif isinstance(x, unicode):
                    li.append((_c.STRING, str(o)))
                    raise TypeError(
                        "list element of type %s cannot be converted" % t0)
            return (_c.MULTIFIELD, li)

    It looks like a simple mistake that instead of adding 'x', the element of the list, it is trying to append 'o', the original list itself. I'll make sure I have the latest version and if it's not fixed there I'll submit a bug report.

  • Francesco Garosi


    sorry for answering so late. In fact it could be such a mistake: while x is something that has a built-in conversion method for each of the considered type, o has been acknowledged as a pure Python sequence (list or tuple, in fact: sets are not taken into account as they have no actual CLIPS equivalent).

    I'd be glad if you open a bug on SF: I'll investigate and fix it ASAP.

    Thank you,


  • Dave

    Dave - 2012-07-27

    Thanks.  I've submitted a bug report with a small patch file.



Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

No, thanks