Sorting algorithm of multifield variable in CLIPS

54 Views Asked by At

I jsut started to learn CLIPS and I made a simple sorting algorithm to sort multifield variables in ascending order, the problem is that the return multifield variable isn't modified during the algorithm

    (deffunction sort (?multifield)
        (bind ?size (length$ ?multifield))
        (loop-for-count (?i 1 (- ?size 1))
            (loop-for-count (?j (+ ?i 1) ?size)
                (printout t (nth$ ?i ?multifield) " " (nth$ ?j ?multifield) crlf)
                (if (> (nth$ ?i ?multifield) (nth$ ?j ?multifield)) then
                    (printout t "> " (nth$ ?i ?multifield) " " (nth$ ?j ?multifield) crlf)
                    (bind ?temp (nth$ ?i ?multifield))
                    (replace$ ?multifield ?i ?i (nth$ ?j ?multifield))
                    (replace$ ?multifield ?j ?j ?temp)
                    (printout t "> que" (nth$ ?i ?multifield) " " (nth$ ?j ?multifield) crlf)
                )
            )
        )
        (return ?multifield)
)

This is a simple case where you can see the printed conditions and a correct execution of the algorithm but an incorrect return value:

CLIPS>  (sort (create$ 3 6 4 1))
3 6
3 4
3 1
before replacement multifield(i) and multifield(j) 3 1
after replacement multifield(i) and multifield(j) 3 1
6 4
before replacement multifield(i) and multifield(j) 6 4
after replacement multifield(i) and multifield(j) 6 4
6 1
before replacement multifield(i) and multifield(j) 6 1
after replacement multifield(i) and multifield(j) 6 1
4 1
before replacement multifield(i) and multifield(j) 4 1
after replacement multifield(i) and multifield(j) 4 1
(3 6 4 1)
1

There are 1 best solutions below

1
derpirscher On BEST ANSWER

Citing from the docs

The replace$ function replaces a range of field in a multifield value with a series of single-field and/or multifield values and returns a new multifield value containing the replacement values within the original multifield value.

So, replace$ does not modify the multifield passed in, but returns a new mutifield with the replaced values, which you have to bind again ...

(deffunction mysort (?multifield)
    (bind ?size (length$ ?multifield))
    (loop-for-count (?i 1 (- ?size 1))
        (loop-for-count (?j (+ ?i 1) ?size)
            (printout t (nth$ ?i ?multifield) " " (nth$ ?j ?multifield) crlf)
            (if (> (nth$ ?i ?multifield) (nth$ ?j ?multifield)) then
                (printout t "> " (nth$ ?i ?multifield) " " (nth$ ?j ?multifield) crlf)
                (bind ?temp (nth$ ?i ?multifield))

                (bind ?multifield (replace$ ?multifield ?i ?i (nth$ ?j ?multifield)))
                (bind ?multifield (replace$ ?multifield ?j ?j ?temp))

                ; or you can do the two above replacements in one call
                ; (bind ?multifield (replace$ (replace$ ?multifield ?i ?i (nth$ ?j ?multifield)) ?j ?j ?temp)) 

                (printout t "> que" (nth$ ?i ?multifield) " " (nth$ ?j ?multifield) crlf)
            )
        )
    )
    (return ?multifield)
)