'Learning LISP - Defining a stdev function

I am very new to LISP (so forgive me for any dumb mistakes) and the first lab of the year states:

Define a function, STDEV that will compute the standard deviation of a list of numbers (look up formula)

I wrote this code but I don't know why it refuses to work:

(defun stdev (x)
  (sqrt (/ (apply '+ (expt (- x (/ (apply '+ x)
                                   (length x)))
                           2))
           (length x))))

(setq a '(1 2 3 4 5))

(STDEV a)

But on runtime it produces the error:

(1 2 3 4 5) is not a number

I believe that I have correctly emulated the standard deviation formula (though I wouldn't put it past myself to make a dumb mistake), but why does my program not like the list of numbers that I give it to evaluate? It is most likely a simple mistake with inputs from this new style of coding but any and all help is greatly appreciated!



Solution 1:[1]

Use indentation. I've edited your question:

(defun stdev (x)
  (sqrt (/ (apply '+ (expt (- x (/ (apply '+ x)
                                   (length x)))
                           2))
           (length x))))

expt returns a number. You call (apply '+ some-number)?

Also you subtract a number from a list.

Why?

Generally I would recommend to use a Lisp listener (aka REPL) to get to working code:

Compute the mean value:

CL-USER 21 > (let ((l (list 1 2 3 4 5)))
               (/ (reduce #'+ l)
                  (length l)))
3

Subtract the mean value and square using mapcar:

CL-USER 22 > (mapcar (lambda (item)
                       (expt (- item 3) 2))
                     (list 1 2 3 4 5))
(4 1 0 1 4)

Compute the variance as the mean value of above:

CL-USER 23 > (let ((l (list 4 1 0 1 4)))
               (/ (reduce #'+ l)
                  (length l)))
2

Take the square root to get the standard deviation:

CL-USER 24 > (sqrt 2)
1.4142135

Then you only need to assemble it into a few functions: average, variance and standard-deviation.

Solution 2:[2]

You’re taking - a ..., when a is your list.

Not a complete answer, because this is homework, but: you want to calculate the mean first, you can implement a sum function, which you will need twice, with a fold, and you can apply a helper function or lambda expression to every element of a list using a map.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2