ACL(1) Lispの世界へようこそ

ポール・グレアムANSI Common Lispを読んでいきたいと思います(優先度低め)。本の略名はACLと勝手に命名しました。

2章からバリバリ変態モード全開なので軟弱者の僕はScheme使っちゃうよ〜。

練習問題 2.1

評価る値を述べよ。

(+ (- 5 1) (+ 3 5))               ; 12
(list 1 (+ 2 3))                  ; (1 5)
(if (pair? 1) (+ 1 2) (+ 3 4))    ; 7
(list (and (pair? 3) #t) (+ 1 2)) ; (#f 3)
  • and,orは、最後に評価した値を返す。
  • Schemeの場合、#f以外は全て真になる。CLの場合nil以外は全て真。

知らなかった・・・。

練習問題 2.2

こんす

(cons 'a (cons 'b (cons 'c '()))) ; (a b c)
(cons 'a (cons 'b '(c)))          ; (a b c)
(cons 'a '(b c))                  ; (a b c)

練習問題 2.3

大きい方を返す

(define (max a b)
  (if (> a b)
      a
      b))

(max 1 2) ; 2

発展。リスト中の最大値を返す。

(define (max l)
  (define (iter n a)
    (if (null? a)
        n
        (iter (if (> (car a) n)
                  (car a)
                  n)
              (cdr a))))
  (iter (car l) (cdr l)))

(max '(1 3 5 7 6 4 2)) ; 7

問題 2.5

aは(1 () 2 3)のようなリストの検出。変態杉。
bはxのあるindexを返す。

問題 2.6

cdr,or,apply。

(car (car (cdr '(a (b c) d))))
(or 13 (/ 1 0))
(apply list 1 2 3 '())

applyってこんなことも出来るのか・・・。

問題 2.7

リスト中にリストを含んでいるかどうか。つまり、ツリーかどうか。

(define (tree? l)
  (cond ((null? l) #f)
        ((or (null? (car l))
             (pair? (car l)))
         #t)
        (else
          (tree? (cdr l)))))

list?でもオッケー。

問題 2.8

再帰と反復でn回ドットをを表示。format使った。

(define (doter n)
  (if (= n 0)
      ""
      (format ".~a" (doter (- n 1)))))

(define (doter n)
  (letrec
    ((iter (lambda (n s)
             (if (= n 0)
                 s
                 (iter (- n 1) (format ".~a" s))))))
    (iter n "")))

; do-0-n-display
(define (doter n)
  (do
    ((i 0 (+ i 1)))
    ((= i n) (display "\n"))
    (display ".")))

; do-n-0-format-nobody
(define (doter n)
  (do
    ((i n (- i 1))
     (s "" (format ".~a" s)))
    ((= i 0) s)))

(doter 10) ; ..........

do版も。

doは終了したら何かを返せる。forは破壊的な更新をしなければならないが、doなら破壊的な更新がいらない。forよりdoの方が断然セクシーだ。iterとか書かなくてもいいし。

doにbody部がいらないけど、活用出来そうな構文。doラブになりそうだ(笑

SICP読むときは、iterで。ACL読むときはdo活用でいこう〜。


bは略

問題 2.9

正しく直せ。

  • aはletが無い
  • bはnullを見る位置が悪い。

感想

lambdaを抜いても良いという話はちょっと面白かった。うぅん。うまくいくのかな・・・妄想・・・。

これが、

(((lambda (x) (lambda () (+ 1 x))) 2))

こう書けるってことになる。

((((x) (() (+ 1 x))) 2))

うまくいくのかな・・・。

((binds...

となっていたら、lambdaであると定義すると、

((((x) (() (+ 1 x))) 2))
((<lambda> 2))
({[x = 2] (() (+ 1 x))}) ; 中を処理。
(<lambda>)
3

おぉ、色々面倒そうだけど、なんとか出来そうな予感。