schemeracketcdr

Scheme: "Contract Violation" when trying to compare elements of two lists


I am trying to compare elements in two different lists in scheme, using DrRacket. If m1 is less than m2, I need to return true. Otherwise, return false. I am getting the following error:

<: contract violation expected: real? given: (3) argument position: 1st other arguments...:

Would appreciate any guidance.

Thanks!

#lang scheme

(define t '( "Apple" 3))
(define t2 '("Orange", 1))


(define compare (lambda (m1 m2)
                (if (<(cdr m1)(cdr m2)) #t #f)
                  ))

(compare t t2)

Solution

  • The cdr of a list like ("Apple" 3) is not 3 but, as the error message tells you, a list with a single element: (3). You cannot compare lists with the function <, which is thus signalling the contract violation.

    Graphically:

    m1 --> [A|Y]
            | |-----> [A|Y]
         car|  cdr     | |-------> NIL
            V       car|   cdr
          "Apple"      V
                       3
    

    Thus:

    (car m1) ;; "Apple"
    (cdr m1) ;; (3)
    (car (cdr m1)) ;; 3
    

    (car (cdr m1)) could also be shortened to (cadr m1). Though note that it's probably better to use first instead of car and rest instead of cdr (if the selected language allows you to).

    Also, don't write

    (if (some-test) #t #f)
    

    when some-test already returns either true or false, just write

    (some-test)