刚开始学习方案

时间:2021-07-02 17:36:08

标签: scheme racket

我不知道为什么这不起作用。我收到一条错误消息:“错误:1 不是函数 [(anon)]”

(define (mem lst ele)
  (cond ;if the list is empty return false
    ((null? lst) #f)
    ;if the first element is equal to the given element return true
    ;otherwise call the function with rest of the list
    (else (if (= ele (car lst)) 
              #t 
              (mem (cdr lst) ele)))))

(mem ’(1) ’(1 4 -2))

3 个答案:

答案 0 :(得分:1)

它对我有用;你怎么称呼mem?我猜你做了类似的事情:(mem (1 2 3 4) 1)。过程调用总是在 Scheme 中评估它们的参数,因此在过程调用 (mem (1 2 3 4) 1) 中评估表达式 (1 2 3 4);但是列表被评估为好像第一个成员是一个过程,所以 1 被视为一个函数;事实并非如此,这引发了一个例外。

您可以引用列表:(mem (quote (1 2 3 4)) 1),也可以使用简写(mem '(1 2 3 4) 1)quote 是一种特殊形式,不评估其参数;相反,它只返回给定的任何数据。你可以在 REPL 上试试这个:

> (+ 1 2)
3
> (quote (+ 1 2))
(+ 1 2)
> '(+ 1 2)
(+ 1 2)

此处裸表达式 (+ 1 2) 的计算结果为 3,但带引号的表达式仅返回赋予 quote 的表达式。也就是说,(quote (+ 1 2)) 的计算结果为表达式 (+ 1 2),而不是表达式 (+ 1 2) 的计算结果。在 (1 2 3 4) 的情况下:

> (quote (1 2 3 4))
(1 2 3 4)
> '(1 2 3 4)
(1 2 3 4)
> (1 2 3 4)

Exception: attempt to apply non-procedure 1
Type (debug) to enter the debugger.

过程调用 (mem '(1 2 3 4) 1) 将在将该值传递给 '(1 2 3 4) 之前计算表达式 mem。由于表达式 '(1 2 3 4) 的计算结果为 list,因此该列表是传递给 mem 的值。这与错误调用 (mem (1 2 3 4) 1) 不同,错误调用 (1 2 3 4) 试图通过使用参数 12 调用(不存在的)过程 3 来评估表达式 4,和list

您还可以使用 (mem (list 1 2 3 4) 1) 创建输入:listmem 也是一个过程,因此它评估其参数。这里对 (list 1 2 3 4) 的调用将评估表达式 list,并且由于 list 是一个过程,因此对 1 的调用将评估参数 2、{{1 }}、34。数字在 Scheme 中是自我评估的,因此对 list 的调用将返回一个列表 (1 2 3 4);这个 list 是传递给 mem 的值,它现在已经评估了它的参数 (list 1 2 3 4)

对已发布代码的一些评论

cond 形式可以采用多个条件子句,这里没有理由使用 if。相反,您可以这样做:

(define (mem lst ele)
  (cond
   ((null? lst) #f)
   ((= ele (car lst)) #t)
   (else
    (mem (cdr lst) ele))))

= 谓词仅适用于数字;要处理更一般的输入,您可以选择equal?

(define (mem lst ele)
  (cond
   ((null? lst) #f)
   ((equal? ele (car lst)) #t)
   (else
    (mem (cdr lst) ele))))

现在您可以使用例如符号列表或列表列表:

> (mem '(a b c d) 'c)
#t
> (mem '(a b c d) 'e)
#f
> (mem '(1 (2 3) 4) '(2 3))
#t
> (mem '(1 (2 (3 4)) 5) '(2 (3 4)))
#t
> (mem '(1 (2 3) 4) 3)  ;; does not descend into nested lists
#f

请注意,将等式谓词更改为 equal? 将允许在输入列表的顶层搜索列表,但不会更深入。列表(2 (3 4))可以在列表(1 (2 (3 4)) 5)中找到,因为它位于列表的顶层,即(2 (3 4))是列表(1 (2 (3 4)) 5)的一个元素。但是,(3 4) 不是顶级列表的元素,因此当前的 mem 过程无法在此处找到它。在嵌套列表中搜索需要 mem 的另一个定义。

答案 1 :(得分:0)

您对文字使用了 acute-accent 而不是单引号。

#lang racket

(define (mem ele lst)  ;;  easier to read with one element -then- list
                       ;;  ..plus that's how you wrote your call to it,
                       ;;  so this arg-order makes more sense here.

  (cond  ;;  cond doesn't need "else"

    ((null? lst) #f)

    ((if (= ele (car lst)) #t
         (mem ele (cdr lst))))  ;; element, then list now
  )
)

(mem 1 '(1 4 -2))
;;  don't know why element needed to be wrapped in a '(1) literal list container
;;  also literals require single-quote ' character, not the ’ acute-accent

https://docs.racket-lang.org/racket-cheat/index.html

答案 2 :(得分:0)

从您的示例看来,您正在查找列表 '(1 4 -2) 中的列表 '(1),其计算结果为 #f。但是,您的实现期望所有元素都是数字,因为您与 = 进行比较,这是一个仅数字比较过程。如果你想比较任何类型,你应该使用 equal? 它比较任何类型的两个对象并支持比较结构。