schemeracketquotetype-mismatchcdr

car/cdr arguments are lists... right?


I made a list of lists of strings called chatbot in Scheme.

Every list element in chatbot have strings. I'm trying to classify these strings using different lists, and these lists are all stored in a big list called chatbot. (sorry for redundance)

To make it clear, here is the code doing this:

(define greetings '("string 1"
                    "string 2"
                    "string 3"
                    "string 4"))

(define cheerUpPhrases '("string 5"
                         "string 6"))

(define congratsPhrases '("string 7"
                          "string 8))

(define didNotUnderstand '("string 8"
                           "string 9"
                           "string 10"))

(define chatbot '(greetings cheerUpPhrases congratsPhrases didNotUnderstand))

I really think this is okay. But later, in a function, I wanted to get "string 3" so I tried to do this:

(caddar chatbot)

and then got this error:

caddar: contract violation
expected: (cons/c (cons/c any/c (cons/c any/c pair?)) any/c)
given: '(greetings cheerUpPhrases congratsPhrases didNotUnderstand)

Not very sure of what that meant, I changed (caddar chatbot) into:

(third (car chatbot))

Finally, I got this error:

third: contract violation
expected: list?
given: 'greetings

Now, I understand (third) needs a list (actually pair) to work; and so are car/cdr and similar functions. Am I not giving it a list after all? I'm really confused now.

I'm just starting with Scheme and the functional paradigm, so I may be missing a basic thing. It would really help me if you could explain me what's going on.

Thanks in advance.


Solution

  • Close. the problem is your misuse of '.

    You see, '(a b c) doesn't expand to something like (list a b c), but rather, it expands to something like (list 'a 'b 'c).

    So, instead of inserting the lists greetings, cheerUpPhrases, congratsPhrases, and didNotUnderstand, you actually inserted them literally as symbols.

    There are two easy ways to get around this. Either you can use quasiquote ` and unquote ,, or you can just use list directly. Rewriting your code as using list (and fixing a your broken "string 8" gives:

    (define greetings '("string 1"
                        "string 2"
                        "string 3"
                        "string 4"))
    
    (define cheerUpPhrases '("string 5"
                             "string 6"))
    
    (define congratsPhrases '("string 7"
                              "string 8"))
    
    (define didNotUnderstand '("string 8"
                               "string 9"
                               "string 10"))
    
    (define chatbot (list greetings cheerUpPhrases congratsPhrases didNotUnderstand))
    

    You can now see that the chatbot variable contains the actual list you were expecting:

    > chatbot
    '(("string 1" "string 2" "string 3" "string 4") ("string 5" "string 6") ("string 7" "string 8") ("string 8" "string 9" "string 10"))