Search code examples
racketcomputer-science

>: expects a real, given (void)


I am currently struggling with creating a list that finds if all the numbers within the list are equal to each other:

(define (list-all-equal lon) (cond [(empty? lon) lon]
                                  [(empty? (rest lon)) (first lon)]
                                  [(empty? (rest (rest lon))) (first lon)]
                                  [(equal? (first lon) (list-all-equal(rest lon))) (write #true)]
                                  [(> (first lon) (list-all-equal(rest lon))) (write #false)]
                                  [(< (first lon) (list-all-equal(rest lon))) (write #false)]
                                  [else (list-all-equal (rest lon))]))

However, I keep on receiving the error: >: expects a real, given void. is there a way to solve the error?


Solution

  • The problem is that you're calling write as part of the recursion, and write "returns" void, which will lead to something like this:

    (> some-number (void))
    

    Never use write to return a value from your procedures! We want to return the results, not to display them on the console. And for this case you have to implement your procedure in such a way that, if it finds a different number, it stops comparing - the result is false and we shouldn't continue. A good strategy would be to pass along the first element and compare the rest against it:

    (define (list-all-equal lst)
      (if (empty? lst)
          #t
          (list-all-equal-helper (first lst) (rest lst))))
    
    (define (list-all-equal-helper ele lst)
      (cond ((empty? lst) #t)
            ((not (= (first lst) ele)) #f)
            (else (list-all-equal-helper ele (rest lst)))))        
    

    Or, we could use apply :)

    (define (list-all-equal lst)
      (apply = lst))
    

    Either way, it works as expected:

    (list-all-equal '(1 2 3))
    => #f
    (list-all-equal '(1 1 1))
    => #t