Home > Back-end >  Scheme program to multiply all the elements of a list together
Scheme program to multiply all the elements of a list together

Time:06-17

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)))))))))))
  • Related