Sasheem
Sasheem

Reputation: 131

Incorrect type for (equal?) comparison in scheme

I'm writing a program in scheme that will allow me to manage a list of information pertaining to a student. Each element of this list is another list containing 3 items about a student: ID (string of digits), student name (string of chars), and grade (integer). I'm currently trying to write a function to sort my list of students by ID in ascending order. Along with this function I trying to write two helper functions, 'smallest' and 'remove'

I've tested my smallest function and it returns the smallest ID correctly. Now I am testing my remove function to see if it will return a list with the student element with the smallest ID removed:

When I make a call to (display (remove roster (smallest roster (car (car roster))))), I get an error saying that ';The object ("4" "lini" "94"), passed as an argument to string->number, is not a string.' The current list when this call is made is: ((5 me 95) (4 lini 94) (3 rudy 93) (2 mark 92) (1 silas 91)). I used the string->number function for a > comparison so I assumed it would work here too, but I'm also not getting the right element of the list that I desire to even compare it with. This caused me to add (car (car (car roster) into the second parameter for (equal?) and it gave me the error ';The object "5", passed as the first argument to car, is not the correct type.'

Does anyone know what I am doing wrong here? I'm also restricted from using set! functions, do-loops, and any built in sort functions.

(define smallest
  (lambda (roster record)
          (if (null? roster)
              (begin (display record) record)
              (if (> (string->number record) (string->number (car (car roster))))
                  (smallest (cdr roster) (car(car roster)))
                  (smallest (cdr roster) record)))
         ))

(define remove
  (lambda (roster record)
     (if (equal? (string->number record) (string->number (car(car(car roster)))))   
          (cdr roster)
          (remove (list (cdr roster) (car roster)) record) 
    )))

(define performtask
  (lambda (n roster)
        (cond ((= n 0) (begin
                        (display "\n\tOption 0.")
                        (display "\nReset Roster")
                        (menu '())
                        ))
              ((= n 1) (begin
                        (display "\n\tOption 1.")
                        (display "\nLoad Roster From File")
                        (menu roster)
                        ))
              ((= n 2) (begin                                   
                        (display "\n\tOption 2.")
                        (display "\nStore Roster To File")
                        (display (list (remove roster (smallest roster (car(car roster))))))
                        (menu roster)
                        ))
              ((= n 3) (begin                                   
                        (display "\n\tOption 3.")
                        (display "\nDisplay Roster by ID")
                        (display "\nsmallest record is: ")
                        (smallest roster (car (car roster)))
                        (menu roster)
                        ))
              ((= n 4) (begin                                   
                        (display "\n\tOption 4.")
                        (display "\nDisplay Student Info")
                        (menu roster)
                        ))
              ((= n 5) (begin                                   
                        (display "\n\tOption 5.\n")
                        (display roster)
                        (newline)
                        (menu (cons (ano-read-3-items 0 '()) roster))
                        ))
              ((= n 6) (begin                                   
                        (display "\n\tOption 6.")
                        (display "\nRemove a student from Roster")
                        (menu roster)
                        ))
              ((= n 7) (begin(display "\n\tOption 7. Exit\n")
                        #t
                        ))
              (else (begin
                        (display "\n\tTask No. ")
                        (display n)
                        (display " does not exit.\n\n")
                        (menu roster)
                    )
              )
        )
  )
)

(define menu
  (lambda (roster)
        (begin
           (display "\t============================\n")
           (display "\t    MENU\n")
           (display "\t============================\n")
           (display "\t0. Reset roster\n")
           (display "\t1. Load roster from file\n")
           (display "\t2. Store roster to file\n")
           (display "\t3. Display roster sorted by ID\n")
           (display "\t4. Display student information\n")
           (display "\t5. Add a student to roster\n")
           (display "\t6. Remove a student from roster\n")
           (display "\t7. Exit\n")
           (display "\tEnter your choice: ")
           (performtask (read) roster)
        )
  )
)

Upvotes: 0

Views: 95

Answers (1)

Sylwester
Sylwester

Reputation: 48775

So you have problems with the following:

(define roster '(("5" "me" 95) ("4" "lini" 94) ("3" "rudy" 93) ("2" "mark" 92) ("1" "silas" 91)))
(remove roster "1") ; some error

Your error is this part:

(remove (list (cdr roster) (car roster)) record) 

Imagine you are sending in (student1 student2) and student1 isn't the one to remove. Then it recurses with the list ((student2) student1) as argument. The second time around the error shows since the data you are looking for is at a layer lower than you expected. Also the list doesn't get any shorter so if your test did work you would have got infinite recursion.

The solution is to cons the answer. It matches with the base case that evaluates to the tail of the list when the removed object is found thus any previous elements must have been consed before that or else you'd end up with removing everything until the id you were trying to remove. It should look something like (cons non-match1 (cons non-match2 (cdr roster)) Thus the recursion happens in the cdr of the cons:

(cons non-match (remove rest-of-list record))

You probably tried to fix this by adding another car when accessing the id? I see that, unlike smallest that uses caar to get the id you use caaar in remove. It was the first thing I saw and I wondered why.

Upvotes: 0

Related Questions