On Lisp

id:rui314さんのすすめもあって、またOn Lisp を読みはじめる。
以前に何度か目を通したはずがあまり記憶に残ってない。


以前と比べて格段に理解度が上がっている気がするのでもう少し続けよう。
Scheme(Gauche)で所々の例を書いてみています。

;; find-if
(define (find-if func lst)
  (cond ((null? lst) #f)
        ((func (car lst)) (car lst))
        (else (find-if func (cdr lst)))))


(define towns (list 'daikanyama 'shibuya 'ebisu 'meguro))

(define bookshops (lambda (town)
                    (cond ((eq? town 'shibuya) (list "book 1st" "Taiseido"))
                          ((eq? town 'ebisu)   (list "Yurindo Ebisu"))
                          ((eq? town 'meguro)  (list "Yurindo Meguro" "Kappa books"))
                          (else #f))
                    ))

(let ((town (find-if bookshops towns)))
  (values town (bookshops town)))
;; shibuya
;; ("book 1st" "Taiseido")
;; bookshops called twice!

(define find-books (lambda (towns)
  (if (null? towns)
      nil
      (let ((shops (bookshops (car towns))))
        (if shops
            (values (car towns) shops)
            (find-books (cdr towns)))))))

;; gosh> (find-books towns)
;; shibuya
;; ("book 1st" "Taiseido")
;; bookshops called once!

(define find2 (lambda (fn lst)
  (if (null? lst)
      nil
      (let ((val (apply fn (list (car lst)))))
            (if val
                (values (car lst) val)
                (find2 fn (cdr lst)))))))

;; gosh> (find2 bookshops towns)
;; shibuya
;; ("book 1st" "Taiseido")

;; closure network
(define *nodes* (make-hash-table))

(define defnode
  (lambda (name conts . yesno)
    (hash-table-put!
     *nodes*
     name
     (if yesno
         (lambda ()
           (display conts)
           (newline) ;; for flush
           (cond ((eq? 'yes (read)) (apply (hash-table-get *nodes* (car yesno)) '()))
                 (else (apply (hash-table-get *nodes* (cadr yesno)) '()))))
         (lambda () conts)))))

(defnode 'people "Is the person a man?" 'male 'female)
(defnode 'male "Is he living?" 'liveman 'deadman)
(defnode 'deadman "Was he American?" 'us 'them)
(defnode 'us "Is he on a coin?" 'coin 'cidence)
(defnode 'coin "Is the coin a penny?" 'penny 'coins)
(defnode 'penny 'lincoln)

;; gosh> (apply (hash-table-get *nodes* 'people) '())
;; Is the person a man?
;; yes
;; Is he living?
;; no
;; Was he American?
;; yes
;; Is he on a coin?
;; yes
;; Is the coin a penny?
;; yes
;; lincoln