Trung Bún
Trung Bún

Reputation: 1147

Error: contract violation in Scheme

I'm practicing recursion in Scheme. My code below is used to take a pattern clause and a statement then return a list of bindings if statement match pattern, false if it isn't:

(define remove-question-mark
  (lambda (s1)
    (if (memq #\? (string->list (symbol->string s1)))
        (cdr (string->list (symbol->string s1)))
        '())))

(define check-two-symbol
  (lambda (symbol1 symbol2)
    (if (and (regexp-match #rx#"\\?attrs" (symbol->string symbol1)) (list? symbol2))
        (cons symbol1 (list symbol2))
        (if (equal? symbol1 symbol2)
            '()
            (if (equal? (remove-question-mark symbol1) (string->list (symbol->string symbol2)))
                (cons symbol1 symbol2)
                #f)))))

(define clause
  (lambda (state1 state2)
    (if (and (null? (car state1)) (null? (car state2)))
        '() 
        (list (check-two-symbol (car state1) (car state2)) (clause (cdr state1) (cdr state2))))))

This is my input:

(clause '(wasDerivedFrom ?der ?e1 ?e2 . ?attrs_derv) '(wasDerivedFrom der e1 e2 (prov:type "Revision")))

I got this error from my code:

car: contract violation
  expected: pair?
  given: '()

Expected output:

((?der . der)
(?e1 . e1)
(?e2 . e2)
(?attrs_derv (prov:type "Revision")))

After debugging, i found that error happens when (car state1) is ?attrs_derv

If I run function check-two-symbol seperrately, like (check-two-symbol '?attrs-derv '(prov:type "Revision")), it prints out nicely:

(?attrs_derv (prov:type "Revision"))

But with the main function, i get error. So can someone please help me show how to fix this error?? I'm not really familiar with recursion much ....

Thank in advanced!

Upvotes: 1

Views: 16544

Answers (1)

Joshua Taylor
Joshua Taylor

Reputation: 85813

The error message indicates that you're calling car with something that's not a pair. You only call car in four places, so it's one of those in clause. Now clause is only called from clause, so you don't have to go too far to track this down. What sort of values should clause be called with? When you call clause recursively (last line of the following code), you're calling it with (cdr state1) and (cdr state2). Is there any reason to assume that those aren't '()?

(define clause
  (lambda (state1 state2)
    (if (and (null? (car state1)) (car (null? state2)))
        '() 
        (list (check-two-symbol (car state1) (car state2))
              (clause (cdr state1) (cdr state2))))))
                      ------------ ------------

Let's look at what clause gets called with from your initial input:

(clause '(wasDerivedFrom ?der ?e1 ?e2 . ?attrs_derv) '(wasDerivedFrom der e1 e2 (prov:type "Revision")))
(clause '(?der ?e1 ?e2 . ?attrs_derv) '(der e1 e2 (prov:type "Revision")))
(clause '(?e1 ?e2 . ?attrs_derv) '(e1 e2 (prov:type "Revision")))
(clause '(?e2 . ?attrs_derv) '(e2 (prov:type "Revision")))
(clause '?attrs_derv '((prov:type "Revision")))

At this point you're going to try to call car on ?attrs_derv, and that should cause an error, because a symbol isn't a pair. Indeed, if we simplify clause to the following (so that it doesn't call check-two-symbol)

(define clause
  (lambda (state1 state2)
    (if (and (null? (car state1)) (car (null? state2)))
        '() 
        (list (clause (cdr state1) (cdr state2))))))

and then try to call the code you mentioned, we get an error:

> (clause '(wasDerivedFrom ?der ?e1 ?e2 . ?attrs_derv) '(wasDerivedFrom der e1 e2 (prov:type "Revision")))
car: contract violation
  expected: pair?
  given: '?attrs_derv

The fact that you got a different error means that either that call to check-two-symbol makes a call to car somewhere that we don't see, or that the test you showed us didn't line up with the output you showed us. In either case, it looks like you're trying to recurse down two lists in parallel. You're only going to be able to do this if they're both pairs, so you probably want code like

(if (not (and (pair? state1) (pair? state2)))
   <then-something>
   <else-something>)

Upvotes: 3

Related Questions