langlauf.io
langlauf.io

Reputation: 3221

PyClips: Create multislot / multifield containing references to other clips instances

A person can own several cars but a car is owned by exactly one person. In clips

(defclass PERSON
    (is-a USER)
    (role concrete)
    (pattern-match reactive)
    (multislot cars) ; each list element should be a reference to an instance of type CAR
)

(defclass CAR
    (is-a USER)
    (role concrete)
    (pattern-match reactive)
    (slot owner) ; should be a reference to an instance of type PERSON
)

I am using pyclips. Now I would like to link an existing instance of CAR to an existing PERSON instance. My try:

clips_person_instance = clips.FindInstance(name_of_existing_person)
clips_car_instance = clips.FindInstance(name_of_existing_car)

list_of_cars = clips_person_instance.Slots["cars"]
list_of_cars.append(clips_car_instance)
clips_person_instance.Slots["cars"] = list_of_cars

This gives me

TypeError: list element of type <class 'clips._clips_wrap.Instance'> cannot be converted

As far as I can see it is a problem make pyclips add a list of instances to a slot. If it is just a single instance (no list), this works fine:

clips_car_instance.Slots["owner"] = clips_person_instance

My question: How do I "link" to class instances in (py)clips? In OO-words: How to I create an association between two objects? How do I create a "1 to many" relation in (py)clips?

Upvotes: 0

Views: 282

Answers (1)

Gary Riley
Gary Riley

Reputation: 10757

It looks like fact and instance addresses are not fully supported in the python code to the same extent as the other CLIPS primitive data types. I'd suggest storing the instance name rather than the instance address in the multifield value (in this case, use clips_car_instance.Name rather than clips_car_instance). You'll have to use FindInstance to convert the instance name back to an instance address to manipulate the instance.

>>> import clips
>>> clips.Load("classes.clp")
>>> clips.Eval("(make-instance Fred of PERSON)")
<InstanceName 'Fred'>
>>> clips.Eval("(make-instance Toyota of CAR)")
<InstanceName 'Toyota'>
>>> name_of_existing_person = "Fred"
>>> name_of_existing_car = "Toyota"
>>> clips_person_instance = clips.FindInstance(name_of_existing_person)
>>> clips_car_instance = clips.FindInstance(name_of_existing_car)
>>> list_of_cars = clips_person_instance.Slots["cars"]
>>> list_of_cars.append(clips_car_instance.Name)
>>> clips_person_instance.Slots["cars"] = list_of_cars
>>> clips_person_instance.Slots["cars"]
<Multifield [<InstanceName 'Toyota'>]>
>>> 

Upvotes: 1

Related Questions