Sunday, April 30, 2006

[Lisp] car, cdr, cons

car, cdr, cons เป็นคำสั่งพื้นฐานใน Lisp
เริ่มที่ cons ก่อน
cons จะทำหน้าที่สร้าง pair ขึ้นมา
ตัวอย่าง
(cons 1 2) ;; => (1 . 2)

ที่สนุกก็คือ list ก็คือ pair แบบหนึ่ง
(1 2) จริงแล้ว ก็คือ (1 . (2 . nil))
(1 2 3) ก็คือ (1 . (2 . (3 . nil)))

ส่วน car ใช้สำหรับ extract element แรกใน pair
(car (cons 1 2)) ;; => 1

กลับกัน cdr ใช้สำหรับ extract element ที่สอง

(cdr (cons 1 2)) ;; => 2


แต่ที่น่าสนใจคืออันนี้
(ไปเจอใน blog ของ archie maskill
เรื่อง Blurring the Line Between Data and Procedures
)
คำถาม ก็คือ ถ้าเราจะ implement cons, car, cdr ด้วย ภาษา lisp เอง
เราจะเขียนมันอย่างไร
(ตัวอย่างนี้ใช้ dialect scheme)
(define (cons a b)
(lambda (pick)
(cond ((= pick 1) a)
((= pick 2) b))))

(define (car x) (x 1))
(define (cdr x) (x 2))

ดู code แล้ว คนที่ไม่คุ้นกับ functional language ก็จะเริ่มงงนิดๆ
ตรงที่การเรียกใช้ cons a b จะได้ function กลับมา
ส่วน car กับ cde ก็เป็นการเรียกใช้ lambda นั้นๆ

แต่ที่ดูแล้ว ต้องปรับตาปรับใจนานหน่อย ก็ต้องแบบนี้
(define (cons x y)
(lambda (m) (m x y)))

(define (car z)
(z (lambda (p q) p)))

ถ้าค่อยๆ ดู ก็จะเห็นว่า cons return เป็น function ที่รอรับ parameter เป็น function
จากนั้นการเรียกใช้ car ก็คือการ call function ที่ได้จาก cons ด้วย function (lambda (p q) p)

Related link from Roti

No comments: