Apply sum-of-squares to multiple numbers with reduce

Viewed 250

I define square and sum-of-squares as:

(defun square(x)
  (* x x))
(defun sum-of-squares (x y)
  (+ (square x) (square y)))

then apply it an array with reduce:

(reduce 'sum-of-squares '(2 2 2))

but get result as 68 rather than 12.

What's the problem?

2 Answers

The reduction does

(sum-of-squares (sum-of-squares 2 2) 2)

which is

    (sum-of-squares 8 2)

which is 64 + 4

You can get the result you expect with

(reduce #'+ (mapcar #'square '(2 2 2)))

or

(reduce #'(lambda (x y) (+ x (square y))) '(2 2 2) :initial-value 0)

or by defining sum-of-squares to take an arbitrary number of arguments.

I saw your comments:

any ideas to improve the sum-of-squares?

(defun sum-of-squares (&rest lst)
  (let ((value 0))
    (dolist (element lst value)
      (setq value (+ (square element) value)))))

(sum-of-squares 2 2 2)
;; 12

It is faster than reduce . mapcar, because it won't generate intermediate data structure.

Related