This program is meant to multiply all the elements of an array together in scheme and output the total but so far it has only been returning 0 as the output.
(define (mult-list lst)
(if (null? lst)
0
(* (car lst)
(mult-list (cdr lst)))) )
CodePudding user response:
The problem is that 0 * <anything>
is still 0, and the multiplication by 0 gets propagated up the function calls since the last function call will always return 0 (which then gets multiplied by the next number, which is still 0, and the next, still 0, etc).
The solution to this would be to return 1 instead of 0, since 1 is the multiplicative identity the same way 0 is the additive identity. Since anything multiplied by 1 is itself, this will mean that the last item in the list gets multiplied by 1 (still = to the last item) which then gets multiplied by the second-to-last item, etc.
Alternatively, instead of returning 1 when the list is empty, you can return the only item in the list ((car lst)
) when the list has 1 item left in it ((null? (cdr lst))
).
CodePudding user response:
I'm more a fan of Church numerals, which are, along with arithmetic operations on them, expressed as applications of functions in the elegant and fundamental lambda calculus. Note the absence of *
.
(define (mult-list lst)
(letrec ((mul (lambda (m n) (lambda (f) (lambda (x) ((m (n f)) x)))))
(church (lambda (n)
(if (= n 0)
(lambda (f) (lambda (x) x))
(lambda (f) (lambda (x) (f (((church (- n 1)) f) x)))))))
(unchurch (lambda (cn) ((cn (lambda (x) ( x 1))) 0))))
(let loop ((lst (map church lst))
(acc (church 1)))
(if (null? lst)
(unchurch acc)
(loop (cdr lst) (mul (car lst) acc))))))
(write (mult-list '(2 3 4)) ; 24
You might also be interested in the use of a named let to express recursion instead of calling the top-level function directly. Very useful in more complicated functions.
CodePudding user response:
(define mul1 (lambda (l) (apply * l)))
(define mul2 (lambda (l) (reduce-left * 1 l)))
(define mul3
(lambda (l)
((lambda (s) (s s l))
(lambda (s l)
(or (and (null? l) 1)
(* (car l) (s s (cdr l))))))))
And here I wrote for you other method that looks more complicated, but in fact it is simpler, as it multiplies by never using multiplication! It uses only SUB1, ADD, ZERO?. I like the arithmetics of Peano, this is why I proposed you my favorite version.
(define mul/peano
(lambda (l)
(define sub1 (lambda (x) (- x 1)))
((lambda (s) (s s l (lambda (total) total)))
(lambda (s l next)
(or (and (null? l) (next 1))
(and (zero? (car l)) (next 0))
(s s (cons (sub1 (car l)) (cdr l))
(lambda (r1)
(s s (cdr l)
(lambda (r2)
(next ( r1 r2)))))))))))