Racket - lang plai - 定义类型和类型案例解释

时间:2015-10-26 06:59:32

标签: scheme racket plai

有人可以尝试解释这两个函数:球拍中PLAI方案中的“define-type”和“type-case”吗?我是一个菜鸟程序员,我不太了解球拍网站上的文档。如果有人能举例,我们将不胜感激。谢谢。

2 个答案:

答案 0 :(得分:3)

以下是如何使用define-typetype-case的一个小例子:

#lang plai

; A ListOfNumbers are either
; is either an empty list of numbers
; or is constructed to two things a, and, d,
; where a is a number and d is a list of numbers.

(define-type ListOfNumbers
  (Empty)
  (Cons (a number?) (d ListOfNumbers?)))

; construct a list of numbers as an example
(define a-list (Cons 42 (Cons 43 (Empty))))    
a-list   ; prints: (Cons 42 (Cons 43 (Empty)))

(type-case ListOfNumbers a-list
  (Empty ()     "the list is empty")
  (Cons (a d)  (~a "the first number in the list is " a)))
; prints: "the first number in the list is 42"

答案 1 :(得分:1)

我对 Lisp/Scheme/Racket 的经验不是很丰富,但看起来这个问题在 5 年后仍然没有答案,所以我会试一试。

首先,请注意并非一切都是函数。例如,当您使用 define 来定义一个函数或某个其他值时,define 不会作为一个函数运行。函数是接受一些输入,然后返回一些输出的东西。 define 不这样做。相反,它会改变您正在编程的环境,从而产生一个可用于引用某个值的新名称。

例如,在...

(define cadr
  (lambda (x)
    (car (cdr x))))

... define 修改了编程环境,以便函数 cadr 现在存在。 cadr 是一个函数(如果你用一些输入调用它,它会产生一些输出),但 define 本身不是一个函数(你不是用一些输入调用 define以获得一些输出)。

希望消除这种区别后,define-type 不是函数。它与 define 类似,因为它修改了编程环境以使其具有新名称来引用某些值。它用于定义新类型,以及一些允许您使用该类型的函数。

取自 Racket 文档的示例:

> (define-type Shape
    [circle (radius : number)]
    [rectangle (width : number)
               (height : number)])

> (define (area [s : Shape])
    (type-case Shape s
      [circle (r) (* (* r r) 3.14)]
      [rectangle (w h) (* w h)]))

> (area (circle 1))
- number
3.14

> (area (rectangle 2 3))
- number
6

这里定义了一个新类型 Shape,它说它有两个变体:circlerectangle。它进一步说,在 circle 变体的情况下,有趣的数据是它的 radius,它是一个数字;而在 rectangle 变体中,有两条数据(或“字段”),它们是它的 widthheight(都是数字)。

然后它定义了一个新函数 area,它应该接受类型为 Shape(我们刚刚声明的类型)的单个输入。 type-case 表达式用于指定如何根据我们正在处理的变体计算 Shape 的面积。如果我们正在处理 circle,那么我们可以通过平方半径并将其乘以 Pi 来计算面积。如果我们处理的是 rectangle,那么我们可以通过将其宽度乘以高度来计算面积。

之前,我说过 define-type 不是函数,但通过使用它,它定义了一个新类型和一堆允许我们使用该类型的函数。那么它定义的这些新功能是什么呢?看这个例子:

> (define c (circle 10))

> c
- Shape
(circle 10)

> (circle? c)
- boolean
#t

> (circle-radius c)
- number
10

> (define r (rectangle 2 3))

> (+ (rectangle-width r) (rectangle-height r))
- number
5

这里我们然后使用 define 来修改编程环境,以便名称 c 指代我们创建的半径为 10 的圆。circle? 是一个函数,当我们在前面的例子中做了 define-type,它返回我们正在处理的 shape 是否是一个 circle 变体(而不是一个 rectangle 变体)。类似地,circle-radiusrectangle-widthrectangle-height 函数是在我们使用 define-type 时自动为我们定义的,它们允许我们访问数据类型内部的字段。