How to return either a multiplied value in a list or boolean in Scheme (R5RS)?

100 Views Asked by At

So I encountered a problem where I have a list of numbers that I need to multiply out and return that value. However, if the list does not contain numbers or is an empty list, return false. Please note that I cannot use any built in functions and would like to understand from scratch in Scheme R5RS. (Example: make-list is a function in Scheme, but can be done recursively without using the function itself)

I implemented a helper function where the base case is if the list is empty, return false. Otherwise, recursively multiply inside the list. However, this doesn't work since the if condition is returning a boolean whereas the recursive method is returning a function.

Also, I have tried returning my base case into a value which is good except for when I am testing an empty list which is suppose to be #f but a value is returned instead.

An example would be:

(mult-this '(2 3 4)) -> 24
(mult-this '(1 2 a b)) -> #f
(mult-this '()) -> #f

Here is my psuedo-code (helper)

(define multiply-this (lambda (mult)
(if (null? mult)
#f
(* recursively multiply car mult and cdr mult)
1

There are 1 best solutions below

2
Shawn On

One pure-R5RS way:

(define (mult-this lst)
  (if (null? lst)
      #f
      (let loop ((product 1)
                 (numbers lst))
        (cond
         ((null? numbers) product)
         ((number? (car numbers))
          (loop (* product (car numbers)) (cdr numbers)))
         (else #f)))))

Basically, it first checks for an empty list, and then for the non-empty case, it recursively iterates over the list using a named let, multiplying together numbers as it goes, and returning early with #f if it encounters a non-number value before the end of the list.

Example usage:

#;1> (load "mult.scm")
; loading mult.scm ...
#;2> (mult-this '(2 3 4))
24
#;3> (mult-this '(1 2 a b))
#f
#;4> (mult-this '())
#f