3.9 Maybe
Nil的安全类型,在类型上避免空指针错误。
3.9.1 Maybe类型定义
3.9.2 操作
这引来一个问题,那么我们该如何得到Just #f呢?我的答案是直接调用(Just #f)。
> (->maybe 1) (Just 1)
> (->maybe 0) (Just 0)
> (->maybe #f) (Nothing)
> (Just #f) (Just #f)
> (->maybe #t) (Just #t)
procedure
(maybe-filter f ma) → (Maybe/c a)
f : (-> a boolean?) ma : (Maybe/c a)
> (maybe-filter even? (Just 2)) (Just 2)
> (define (gt xs) (> (length xs) 5)) > (maybe-filter gt (Just (array 1 2 3))) (Nothing)
> (maybe-filter gt (Just (array 1 2 3 4 5 6))) (Just (Array 1 2 3 4 5 6))
> (maybe-and (Just 1) nothing) (Nothing)
> (maybe-and (Nothing) (Just 2)) (Nothing)
> (maybe-and (Just 1) (Just 2)) (Just 2)
> (maybe-or (Just 1) nothing) (Nothing)
> (maybe-or (Nothing) (Just 2)) (Nothing)
> (maybe-or (Just 1) (Just 2)) (Just 1)
> (maybe-alt (Just 1) (Just 2)) (Just 1)
> (maybe-alt (Just 1) (Nothing)) (Just 1)
> (maybe-alt nothing (Just 2)) (Just 2)
> (maybe-else 10 add1 (Just 1)) 2
> (maybe-else 10 add1 nothing) 10
procedure
(maybe-just msg x) → a
msg : string? x : (Maybe/c a)
> (maybe-just "这里不会显示" (Just 1)) 1
> (maybe-just "我不能啊" (Nothing)) 我不能啊
procedure
(maybe-unwrap x) → y
x : (Maybe/c y)
> (maybe-unwrap (Just 1)) 1
> (maybe-unwrap (Just #f)) #f
> (maybe-unwrap nothing) maybe-unwrap: 试图解包nothing!
语法
(maybe-catch expr)
expr = 任何表达式
> (maybe-catch (* 1 0)) (Just 0)
> (maybe-catch (/ 1 0)) (Nothing)
3.9.3 Maybe的do记法
syntax
(maybe/do expr ...+)
expr = 普通表达式 | 赋值表达式 | 中断表达式 | 副作用表过式 赋值表达式 =
| (let id = expr) | (id <- expr) 中断表达式 =
| (break) | (break 值) 副作用表过式 =
| (! 任意表达式 ...+)
在赋值表达式中,(id <- expr)这种形式,会对expr结果进行封装,如果是普通值(非Maybe),会以->maybe包装后再进行相关流程。(let)表达式就是纯粹赋值,没有多余处理流程。
> (define (f n) (and (< n 5) n))
> (maybe/do (a <- (f 1)) (b <- (f 2)) (+ a b)) (Just 3)
> (maybe/do (a <- (f 1)) (b <- (f 10)) (+ a b)) (Nothing)
> (maybe/do (let a = (f 1)) (let b = (f 10)) (+ a b)) +: contract violation
expected: number?
given: #f
break可以中断操作,提前跳转整个代码块。它可以接受一个参数或无参数:接受一个参数,该参数自动封装成maybe?(除非已经是Maybe);无参数返回nothing。
> (maybe/do (a <- 1) (when (= a 1) (break 10)) (! (displayln a)) (add1 a)) (Just 10)
> (maybe/do (a <- 1) (unless (= a 10) (break)) a) (Nothing)
!仅仅用来处理副作用的代码。需要IO处理(如打印、读写文件),又不想中断整个操作,那么可以使用该形式表过式。不管它最终结果是什么,都不会中断后面代码!