Racket编程指南——4 表达式和定义(七)

78 篇文章 16 订阅

4.10 引用:quote和'

在《Racket参考》中“(quote)”部分也有关于quote的文档。

quote表产生一个常数:

(quote datum)

datum的语法在技术上被指定为read函数解析为一个单个元素的任何内容。quote表的值是相同的值,其read将产生给定的datum

datum可以是一个符号、一个布尔值、一个数值、一个(字符或字节)字符串、一个字符、一个关键字、一个空列表、一个包含更多类似值的点对(或列表),一个包含更多类似值的向量,一个包含更多类似值的哈希表,或者一个包含其它类似值的格子。

Examples:

> (quote apple)

'apple

> (quote #t)

#t

> (quote 42)

42

> (quote "hello")

"hello"

> (quote ())

'()

> (quote ((1 2 3) #("z" x) . the-end))

'((1 2 3) #("z" x) . the-end)

> (quote (1 2 . (3)))

'(1 2 3)

正如上面最后的示例所示,datum不需要匹配一个值的格式化的打印表。一个datum不能作为一个以#<开始的打印呈现,所以不能是#<void>、#<undefined>或一个过程。

quote表很少用于一个datum,它是一个布尔值、数字或字符串本身,因为这些值的打印表已经可以用作常量。quote表更常用于符号和列表,当没有被引用时,它具有其它含义(标识、函数调用等等)。

一个表达式:

'datum

是以下内容的一个简写

(quote datum)

这个简写几乎总是用来代替quote。这个简写甚至应用于datum中,因此它可以生成一个包含quote的列表。

在《Racket参考》里的“(parse-quote)”提供有更多关于'简写的内容。

Examples:

> 'apple

'apple

> '"hello"

"hello"

> '(1 2 3)

'(1 2 3)

> (display '(you can 'me))

(you can (quote me))

4.11 准引用:quasiquote和‘

在《Racket参考》中的“(quasiquote)”部分也有关于quasiquote的文档。

quasiquote表类似于quote:

(quasiquote datum)

然而,对出现在datum之中的每个(unquote expr),expr被求值以产生一个替代unquote子表的值。

Example:

> (quasiquote (1 2 (unquote (+ 1 2)) (unquote (- 5 1))))

'(1 2 3 4)

此表可用于编写根据特定模式建造列表的函数。

Examples:

> (define (deep n)
    (cond
      [(zero? n) 0]
      [else
       (quasiquote ((unquote n) (unquote (deep (- n 1)))))]))
> (deep 8)

'(8 (7 (6 (5 (4 (3 (2 (1 0))))))))

甚至可以以编程方式方便地构造表达式。(当然,第9次就超出了10次,你应该使用一个《》来做这个(第10次是当你学习了一本像《PLAI》那样的教科书之后)。)

Examples:

> (define (build-exp n)
    (add-lets n (make-sum n)))
> (define (add-lets n body)
    (cond
      [(zero? n) body]
      [else
       (quasiquote
        (let ([(unquote (n->var n)) (unquote n)])
          (unquote (add-lets (- n 1) body))))]))
> (define (make-sum n)
    (cond
      [(= n 1) (n->var 1)]
      [else
       (quasiquote (+ (unquote (n->var n))
                      (unquote (make-sum (- n 1)))))]))
> (define (n->var n) (string->symbol (format "x~a" n)))
> (build-exp 3)

'(let ((x3 3)) (let ((x2 2)) (let ((x1 1)) (+ x3 (+ x2 x1)))))

unquote-splicing表和unquote相似,但其expr必须产生一个列表,而且unquote-splicing表必须出现在一个产生一个列表或一个向量的上下文里。顾名思义,这个结果列表被拼接到它自己使用的上下文中。

Example:

> (quasiquote (1 2 (unquote-splicing (list (+ 1 2) (- 5 1))) 5))

'(1 2 3 4 5)

使用拼接,我们可以修改上边我们的示例表达式的构造,以只需要一个单个的let表达式和一个单个的+表达式。

Examples:

> (define (build-exp n)
    (add-lets
     n
     (quasiquote (+ (unquote-splicing
                     (build-list
                      n
                      (λ (x) (n->var (+ x 1)))))))))
> (define (add-lets n body)
    (quasiquote
     (let (unquote
           (build-list
            n
            (λ (n)
              (quasiquote
               [(unquote (n->var (+ n 1))) (unquote (+ n 1))]))))
       (unquote body))))
> (define (n->var n) (string->symbol (format "x~a" n)))
> (build-exp 3)

'(let ((x1 1) (x2 2) (x3 3)) (+ x1 x2 x3))

如果一个quasiquote表出现在一个封闭的quasiquote表里,那这个内部的quasiquote有效地取消unquote表和unquote-splicing表的一层,结果一个第二层unquote或unquote-splicing表被需要。

Examples:

> (quasiquote (1 2 (quasiquote (unquote (+ 1 2)))))

'(1 2 (quasiquote (unquote (+ 1 2))))

> (quasiquote (1 2 (quasiquote (unquote (unquote (+ 1 2))))))

'(1 2 (quasiquote (unquote 3)))

> (quasiquote (1 2 (quasiquote ((unquote (+ 1 2)) (unquote (unquote (- 5 1)))))))

'(1 2 (quasiquote ((unquote (+ 1 2)) (unquote 4))))

上面的求值实际上不会像显示那样打印。相反,quasiquote和unquote的速记形式将被使用:`(即一个反引号)和,(即一个逗号)。同样的简写可在表达式中使用:

Example:

> `(1 2 `(,(+ 1 2) ,,(- 5 1)))

'(1 2 `(,(+ 1 2) ,4))

unquote-splicing的简写形式是,@:

Example:

> `(1 2 ,@(list (+ 1 2) (- 5 1)))

'(1 2 3 4)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值