Racket
ภาษา
Racket เป็นลูกหลานหนึ่งของภาษา LISP อ่านรายละเอียดเพิ่มเติมได้ที่ เอกสาร scheme
Racket มี IDE ชื่อ DrRacket สามารถดาว์นโหลดได้ที่เว็บไซต์ของ Racket
REPL
ส่วนล่างของจอ จะเป็น read-eval-print-loop คือพิมพ์ expression เข้าไป ระบบจะอ่าน คำนวณแล้วก็พิมพ์คำตอบ เช่น
> 5 5 > (+ 10 5) 15 > "hello" "hello" > (substring "hello" 1 3) "el" > (+ (* 4 5) 2) 22
ไวยากรณ์พื้นฐานของภาษา Racket คือการเรียกฟังก์ชัน:
(ฟังก์ชัน อาร์กิวเมนท์1 อาร์กิวเมนท์2 ...)
เราจะไม่สามารถเขียนวงเล็บเล่น ๆ ได้เลย เช่น ถ้าสั่ง (5) จะได้ error ดังนี้
> (5) . . application: not a procedure; expected a procedure that can be applied to arguments given: 5 arguments...: [none]
define
ตัวอย่าง
(define (inc x) (+ x 1)) (define (dec x) (- x 1)) (define (square x) (* x x))
if
(define (myadd a b) (if (= b 0) a (myadd (inc a) (dec b))))
list
- การใช้ quote (')
ถ้าใช้เครื่องหมาย single quote (') นำหน้า Racket จะไม่ evaluate วงเล็บนั้น แต่จะสร้าง list แทน
> (1 2 3 4) . . application: not a procedure; expected a procedure that can be applied to arguments given: 1 arguments...: 2 3 4 > '(1 2 3 4) '(1 2 3 4)
- การใช้ procedure list
โปรดอ่านprocedure เกี่ยวกับ list
โครงสร้างของ list
อันที่จริงแล้ว list มีนิยามว่า
- อาจจะเป็น list ว่าง (null)
- อาจจะเป็น pair (ใน racket เรียกว่า cons มาจาก construct) ของ ข้อมูล กับ list
ข้างล่างนี้คือตัวอย่างของโครงสร้างของ list
โครงสร้างเต็ม | รูปแบบโดยใช้ quote |
---|---|
null | '() |
(cons 1 null) | '(1) |
(cons "a" (cons "b" (cons "c" (cons "z" (cons "" null))))) | '("a" "b" "c" "z" "") |
procedure เกี่ยวกับ list
ชื่อ procedure | คำอธิบาย | ตัวอย่าง |
---|---|---|
list | สร้าง list -- มีความแตกต่างกับการใช้ quote สร้าง list เล็กน้อย แต่โดยทั่วไปแล้วจะเหมือนกัน ใช้แทนกันได้ |
> (list 1 2 3) '(1 2 3) > (list) '() |
null / empty | สร้าง '() ทั้งสอง procedure นี้เหมือนกันทุกประการ ใช้แทนกันได้ |
> null '() > empty '() |
cons | สร้าง pair |
> (cons 1 null) '(1) > (cons 1 '(1 2 3 4)) '(1 1 2 3 4) |
list? | ทดสอบว่าเป็น list หรือไม่ |
> (list? null) #t > (list? '(1 2 3)) #t |
null? / empty? | ทดสอบว่าเป็น '() หรือไม่ |
> (null? null) #t > (null? '(1 2 3)) #f |
cons? | ทดสอบว่าเป็น cons -- กล่าวคือ list ที่ไม่ใช่ '() -- หรือไม่ |
(cons? '()) > #f (cons? '(1)) > #t |
first | ดึงข้อมูล (ตัวแรก) |
> (first '(1 2 3)) 1 > (first '()) first: contract violation expected: (and/c list? (not/c empty?)) given: '() |
rest | ดึง list ของข้อมูลทั้งหมดนอกจากข้อมูลตัวแรก |
> (rest '(1 2 3)) '(2 3) > (rest '(1)) '() > (rest '()) rest: contract violation expected: (and/c list? (not/c empty?)) given: '() |
procedure ทั้งหมดในตารางใช้เวลา
- สังเกตว่าที่ racket สามารถหา rest ได้อย่างรวดเร็ว เนื่องจากโครงสร้างของ list ที่จริงแล้วคือ cons ซ้อนกัน การหา rest อันที่จริงแล้วจึงเป็นเพียงแค่การหาข้อมูลตัวหลังของ cons ตัวนอกสุด
การดำเนินการกับ list
(define (mylen lst) (if (null? lst) 0 (+ 1 (mylen (rest lst))))) > (mylen '("a" "b" "c" "d")) 4
lambda
local variables: let, let*
(define (f x) (let ([x1 (+ x 1)] [x2 (+ x 2)]) (+ x1 x2)))
Useful functions
- equal?
> (equal? '() empty) #t == แบบฝึกหัด 1 == 1. mysum <pre> > (mysum '(1 2 3)) 6
2. mymax
> (mymax '(1 2 3 -1)) 3
3. myappend
> (myappend '(1 2 3 4) 100) '(1 2 3 4 100)
4. myreverse
> (myreverse '(1 2 3 4)) '(4 3 2 1)
5. myconcat
> (myconcat '(1 2 3 4) '(10 20 30)) '(1 2 3 4 10 20 30)
6. myslice
> (myslice '(1 2 3 4 5 6 7) 3 6) '(4 5 6)
7. myrange
> (myrange 5 10) '(5 6 7 8 9)
8. mycascade
> (mycascade '(1 2 3 4 5 6)) '(1 (2 (3 (4 (5 (6))))))
9. myflatten
> (myflatten '(1 (2 3) 4 (5 (6 7)))) '(1 2 3 4 5 6 7)
Tail recursion
(define (fact1 n x) (if (= n 0) x (fact1 (- n 1) (* n x)))) (define (fact n) (fact1 n 1))
Binary search tree
Representing BST
(define T '(5 (3 () (4 () ())) (12 (7 () (9 () ())) (15 () ()))))
Accessing value, left child, and right child
> (car T) 5 > (first (rest T)) '(3 () (4 () ())) > (cadr T) '(3 () (4 () ())) > (caddr T) '(12 (7 () (9 () ())) (15 () ()))
Seaching (using if)
(define (contains? node val) (if (null? node) #f (let ([nv (car node)] [lchild (cadr node)] [rchild (caddr node)]) (if (= val nv) #t (if (< val nv) (contains? lchild val) (contains? rchild val))))))
Searching (using cond)
(define (contains? node val) (if (null? node) #f (let ([nv (car node)] [lchild (cadr node)] [rchild (caddr node)]) (cond [(= val nv) #t] [(< val nv) (contains? lchild val)] [else (contains? rchild val)]))))
ท่าพื้นฐาน
functional programming
filter, map, fold
Examples
Quicksort
(define (qsort lst) (cond [(empty? lst) empty] [(cons? lst) (let ([pivot (first lst)] [r (rest lst)]) (append (qsort (filter (lambda (e) (< e pivot)) r)) (append (list pivot) (qsort (filter (lambda (e) (>= e pivot)) r)))))]))