wvxvw wrote:I used eq because I knew beforehand that the list will only contain numbers and symbols
EQ is not defined to work reliably on numbers. It compares pointer equality and some numbers, especially those that do not fit into machine word minus tags, might be multiply instantiated. There isn't really reason not to ever use EQL.
wvxvw wrote:EDIT: gugamilare, I checked out the Alexandria's code, but could find only map-combinations function, not map-product, is that what you meant?
What version of Alexandria did you look at? Version from quicklisp has map-product in lists.lisp.
EDIT: Of course, map-product doesn't exactly do what you want, since it doesn't short-curcuit when it finds the first counter-example. You can do something like this (minimally tested):
Code: Select all
(defun find-on-self-product (function list n)
(if (zerop n)
(funcall function)
(find-if #'(lambda (x)
(find-on-self-product (alexandria:curry function x)
list
(1- n)))
list)))
(defun operation-associative-p (operation set)
(flet ((optest (x y z)
(let ((a (funcall
operation x (funcall operation y z)))
(b (funcall
operation (funcall operation x y) z)))
(if (eql a b)
(format t "~a * (~a * ~a) = ~a <=> (~a * ~a) * ~a = ~a~&"
x y z a x y z b)
t))))
(not (find-on-self-product #'optest set 3))))
But I am not sure whether it actually simplifies anything. Also note that it uses alexandria:curry, but that is fairly trivial. In any case I would recommend extracting the test itself, having large block of code heavily indented is never good.