引用

复习 quote 特殊形式、eq? 谓词和 memq 的用法,为 calc.rkt 做准备。

本节是对 quote 函数(更常见的形式是 ')及其功能的简短复习和概述,帮助你为下一节 calc.rkt 做准备。

复习

从本课程一开始,我们就用引用(quotation)' 作为创建单词和句子的快捷方式。下面的例子应该极其简单易懂:

> (define a 3)
3

> a
3

> 'a
a

单引号的用法其实是个快捷方式——'a 等价于 (quote a)。类似地,'(a 1 b 2) 等价于 (quote (a 1 b 2))

测试理解

quote(')函数是一个特殊形式。

选项:

  • True:正确!(✅)如果 quote 不是特殊形式,那么当我们调用上面的 (quote a) 时,Racket 会先对实参求值,把表达式化简为 (quote 3),从而返回 3。那就错了!
  • False

谓词与引用

要检查相等性,我们可以用原语 eq?

> (eq? 'a 'a)
#t
> (eq? 'a 'b)
#f
> (eq? 'a (first 'afro))
#t

另一个处理符号/引用的有用原语是 memq。memq 接受两个参数——一个符号和一个列表。如果符号不在列表中(即与列表中任何一项都不 eq?),memq 返回 false。否则,它返回列表中从该符号首次出现处开始的子列表:

>(memq 'apple '(banana raspberry windows android))
#f
>(memq 'apple '(banana raspberry windows apple android))
(apple android)
>(memq 'apple '(banana raspberry windows (apple android))
#f

注意,最后一个例子返回 #f,因为 (eq? 'apple '(apple android)) 返回 #f。因此,memq 不适用于深列表。

你可以用下面的定义自己实现 memq:

(define (memq item x)
  (cond ((null? x) false)
        ((eq? item (car x)) x)
        (else (memq item (cdr x)))))

测试理解

下面这些表达式返回什么?

(memq 'everything '(sugar spice (everything nice)))

(memq 'chicken '(cow chicken cow and chicken))

选项(第一问):

  • (everything nice)
  • everything
  • #f:正确!(✅)memq 不适用于深列表,无法在更深的层次中找到元素。

选项(第二问):

  • (chicken cow and chicken):正确!(✅)看一下 memq 的代码,我们从列表 x 的开头开始,一旦找到 item 就停下。也就是说,遇到 item 在 x 中第一次出现后,我们就会立即返回。
  • (chicken)
  • #f

Racket 会打印什么?

对于下面每个表达式,先在不使用解释器的情况下预测 Racket 会打印什么。然后,用解释器检查你的答案。

  • (list 'a 'b 'c)
  • (list (list 'george))
  • (cdr '((x1 x2) (y1 y2)))
  • (cadr '((x1 x2) (y1 y2))
  • (pair? (car '(a short list)))
  • (memq 'red '((red shoes) (blue socks)))
  • (memq 'red '(red shoes blue socks))

要点总结

本小节你学到了:

  • 'hi 是 (quote hi) 的快捷方式。
  • memq 是一个判断符号是否在列表中的谓词。