On this page:
1.1 常見的值與表達式
1.2 控制流
1.3 提前中斷
1.4 Debug
8.6

1 Quick Start

racket 有一個奇特的怪僻,就是每個檔案都必須標明自己的

#lang xxx

,一開始只要先記得

#lang racket

就可以了。

1.1 常見的值與表達式

racket 作為一個實用的程式語言,自然有熟悉的概念出現,下面就簡單條列一些常見的值與表達式吧:

;;; 註解是用 ; 為開頭
"我是字串" ; 字串
#t ; True
#f ; False
1 ; Integer
3.14 ; Float
4/3 ; Real
3+4i ; Complex
e ; 不是,我就只是叫 e 的變數 XD
 
'(1 2 3) ; Listof Integer,也可以寫
(list 1 2 3) ; 兩邊有微妙的差別但暫時還沒有很重要
 
(λ (x) x) ; lambda,也有人翻譯叫匿名函數,也可以寫成
(lambda (x) x) ; 但在 racket 內建 IDE DrRacket 裡面打出 λ 只需要按 command+\ 非常容易
(define x 1) ; 定義變數
(define (id x) x) ; 定義函數,也可以寫成
(define id (λ (x) x)) ; 但並不會比較好讀 :)
 
(set! x 2) ; 重綁定 x(a.k.a. 賦值)
 
(f a b c) ; 函數呼叫,函數是 f,參數是 a b c

1.2 控制流

作為 Lisp 的主要分支之一,racket 到處都是 () [] 等 S expression,並且稱呼 define 等特殊的表達式為 form。 分辨函數與 form 在 racket 中並不容易,但影響其實不,大因為很少有人會需要弄清楚兩者的差別。 [] 與 () 可以隨意替換使用,這有助於改善可讀性。例如 match 這個用來做 pattern matching 的 form:

(match t
  [(t:1 _ _ _) #t]
  [(t:3 a _ c) (a c)]
  [_ #f])

racket 有數種控制流 form:

(define condition? (= 1 1))
;;; if form 應該是最簡單的,條件、then-expr、else-expr
(if condition?
    1
    2)
; 1
;;; cond 後可以接任意個 cond-clause
; 其中每個 cond-clause 都有 test-expr 或是 else pattern
;  test-expr 成立,就會執行整串 body,就像 number? x 展示的那樣
(define (is x)
  (cond
    [(number? x)
     (displayln "do something else")
     "number"]
    [(string? x) "string"]
    [else "unknown"]))
(is "1")
; "string"
(is 2)
; do something else
; "number"
;;; match 就是 pattern matching
; 下面展示了 match  list  match 時解開 list 得到 head tail 的情況
(define (reduce x [r 0])
  (match x
    ['() r]
    [(cons car cdr) (reduce cdr (+ r car))]))
(reduce '(1 2 3))
; 6

更多資訊

1.3 提前中斷

在 racket 中有兩點需要特別注意:

1. 急切求值,簡單來說就是運算會馬上發生,與 Haskell 成為對比。 2. 沒有 return,也沒有 exception。

等等,看到第二點先別急著說這什麼垃圾 www,雖然沒有內建 return 或是 exception,但 racket 提供了更強大的工具 continuation

(define (foo x)
  (let/cc return
    (when (string? x)
      (return x))
    1))
(foo 1)
;;; 1
(foo "a")
;;; "a"
(foo 'a)
;;; 1

雖然在這個案例裡面內建 return 的語言更方便,但 continuation 提供了更多功能,不過這邊就不深入介紹,之後再另開文章寫這個 XD。

1.4 Debug

https://github.com/AlexKnauth/debug 是一個除錯用的函式庫,安裝指令如下

raco pkg install --auto debug

下面是 quick-sort 的案例,展示我們怎麼查看中間狀態

#lang debug racket
 
(define/match (qs l)
  [((list)) l]
  [((cons head tail))
   (define-values (l b)
     #R(partition (lamdba (e) (< e head)) l))
   (append (qs l) (list head) (qs b))])