Search code examples
runtime-errorschemechez-scheme

Scheme error says "attempt to apply non-procedure" when flipping tuples in a list


I'm working through a textbook on programming languages, and one of the exercises was to make a function in Scheme that flips tuples in a list. Here's my code:

; invert : Listof(List(Int,Int)) -> Listof(List(Int,int))
; usage: (invert '((a 1) (a 2) (1 b) (2 b))) -> ((1 a) (2 a) (b 1) (b 2))
(define invert
  (lambda (lst)
    (if (null? lst)
      '()
      (cons
        (flip (car lst))
        (invert (cdr lst))))))
; flip : List(Int,Int) -> List(Int,int)
; usage: (flip '(a 1)) -> (1 a)
(define flip
  (lambda (tuple)
    (if (not (eqv? (length (tuple)) 2))
      (eopl:error 'flip
        "Tuple is not length 2~%")
      (cons (cdr tuple) (car tuple)))))

I tried testing my program in chez-scheme. When I use the test case in the usage comment, I get this error: Exception: attempt to apply non-procedure (a 1). I've never worked with Scheme before, so I'd greatly appreciate any help and advice. Thanks!


Solution

  • You have a coupe of errors in flip, this should fix them:

    (define flip
      (lambda (tuple)
        (if (not (= (length tuple) 2))
            (eopl:error 'flip "Tuple is not length 2~%")
            (list (cadr tuple) (car tuple)))))
    

    In particular:

    • The specific error reported was because of this expression: (tuple). We must not surround variables with (), unless they're procedures that we intend to call.
    • We should use = for comparing numbers, not eqv?.
    • In this expression: (cons (cdr tuple) (car tuple)) there are two issues, for building a list of two elements we use list, not cons. And for accessing the second element we use cadr, not cdr - you should read a bit about how cons, car and cdr are used for building lists.

    Notice that there's a simpler way to solve this problem if we use map; I'll skip error checking for simplicity:

    (define (invert lst)
      (map (lambda (tuple) (list (cadr tuple) (car tuple)))
           lst))