Search code examples
clips

Is it possible to get the parameter args as a single list for a deffunction?


I'd like to write a function all-neq that is like the builtin neq except that it also enforces that no two elements can be the same (instead of only the first one being different than the rest).

So while the output of (neq 3 4 5 5) is TRUE, I want (all-neq 3 4 5 5) to be FALSE, since there are two 5's.

Here's what I've tried, but I keep getting an error regarding the parameter list as an input.

(deffunction all-neq ?args
  (foreach ?arg1 ?args
    (foreach ?arg2 ?args
      (if (and (not (eq ?arg1-index ?arg2-index))
               (eq ?arg1 ?arg2)) then
          (return FALSE))))
  (return TRUE))

Error message for this one is:

[PRNTUTIL2] Syntax Error:  Check appropriate syntax for parameter list.

Solution

  • You can use a wildcard parameter to group all of the remaining arguments of a deffunction into a single multifield value:

             CLIPS (6.31 6/12/19)
    CLIPS> 
    (deffunction all-neq ($?args)
      (foreach ?arg1 ?args
        (foreach ?arg2 ?args
          (if (and (not (eq ?arg1-index ?arg2-index))
                   (eq ?arg1 ?arg2)) then
              (return FALSE))))
      (return TRUE))
    CLIPS> (all-neq 3 4 5 5)
    FALSE
    CLIPS> (all-neq 3 4 5 6)
    TRUE
    CLIPS>
    

    This will also collapse all multifield values into a single multifield value, so you won't get the correct behavior when comparing multifield values:

    CLIPS> (all-neq (create$ 3 4) (create$ 5 5))
    FALSE
    CLIPS> 
    

    In order to get the correct behavior for multifield values, you'd need to create a user-defined function in C as described in the Advanced Programming Guide rather than using a deffunction.