then i do (average (list 2 3 4 5 6)) but it doesnt work
also how can i do that (average 2 3 4 5 6) gives me the average without doing a list?
please help
Name:
Anonymous2010-12-26 21:43
You need to write a loop that checks if the next element of your list is not null. Dividing by 2 won't really work either, seeing that the lenght of your list can vary, keep a counter the counts the elements in your list or use length if you want to make it less performant...
Name:
Anonymous2010-12-26 21:55
how do i do that? its my very first language i dont know how to do that pls help
In Scheme I'd just write:
(define (average . numbers)
(/ (apply + numbers) (length numbers)))
(average 1 2 3)
2
If you insist on using recursion even when there are better ways to handle it, you can write:
(define (average . numbers)
(letrec ((loop
(lambda (total nrs count)
(if (null? nrs) (/ total count)
(loop (+ total (car nrs)) (cdr nrs) (+ count 1))))))
(loop 0 numbers 0)))
However, I find the second kind of code kind of long-winded for such simple tasks, but I guess that's why I'm more of a CLer than a Schemer
In CL, I'd just write:
(defun average (&rest numbers)
(/ (reduce #'+ numbers) (length numbers)))
;; or
(defun average (&rest numbers)
(/ (loop for n in numbers summing n) (length numbers)))
>>6
However, there is one slight disadvantage to your version, you're just passing the length around without actually making use of it, so your average' is nothing more than a sum (apply + nums) which divides at the end. You also traverse the list twice making it take longer than the recursive version which measures the length while both adding the total. I'm guessing your version is similar in speed to my first example, while my second example being faster as the list is only traversed once. In real code, I never consider writing such explicit adding/summing unless it's some code which needs to be optimized (only done after seeing the results of profiling).
Name:
Anonymous2010-12-27 0:52
Oh nvm, just remembered what letrec means, was a bit confused there for a moment. Also i meant to write this ofc:
(define (average . numbers)
(define average' (nums acc count)
(if (null? nums) (/ nums count)
(average' (cdr nums) (+ (car nums) acc) count)))
(average' numbers 0 (length numbers)))
Name:
Anonymous2010-12-27 0:56
You're right ofc. So the final version would be this:
(define (average . numbers)
(define average' (nums acc count)
(if (null? nums) (/ nums count)
(average' (cdr nums) (+ (car nums) acc) (+ count 1))))
(average' numbers 0 0))
The SATORI way to do it (other than >>5):
(define average
(lambda ns
(let loop ((ns ns)
(i 0)
(r 0))
(if (null? ns) (/ r i)
(loop (cdr ns)
(+ i 1)
(+ r (car ns)))))))
I do it in simple declarative point-free style, like this:
average xs -> [l:@!len]:[s:@!sum]:xs s%l
"[s:@!sum]:" binds `s` to the result of applying hypothesis, that `xs` can be represented as sum of its elements
"[l:@!len]:" does same for length
"s%l" divides sum by length