在列表中翻转元组时,方案错误显示 "attempt to apply non-procedure"

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

我正在阅读一本关于编程语言的教科书,其中一个练习是在 Scheme 中创建一个函数来翻转列表中的元组。这是我的代码:

; 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)))))

我尝试在 chez-scheme 中测试我的程序。当我在用法注释中使用测试用例时,出现此错误:Exception: attempt to apply non-procedure (a 1)。我以前从未使用过 Scheme,因此非常感谢任何帮助和建议。谢谢!

您在 flip 中有很多错误,这应该可以解决它们:

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

特别是:

  • 报告的具体错误是因为这个表达式:(tuple)。我们不能用()包围变量,除非它们是我们打算调用的过程。
  • 我们应该使用 = 来比较数字,而不是 eqv?
  • 在这个表达式中:(cons (cdr tuple) (car tuple)) 有两个问题,为了构建一个包含两个元素的 list,我们使用 list,而不是 cons .为了访问第二个元素,我们使用 cadr,而不是 cdr - 您应该了解一下 conscarcdr 是如何用于构建列表的.

请注意,如果我们使用 map,则有一种更简单的方法可以解决此问题;为简单起见,我将跳过错误检查:

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