Hatena::Groupsicp

SICP読書メモ

 | 

2009-03-14

4.1.6 内部定義 00:33

手続き内のdefine式による定義は、振る舞いとしては同時に評価されるべき?


((lambda (n)
  (define a (+ b 10)
  (define b (- n 3))
  (+ a b)))
 10)

という式があった時に、a定義中のbは

- 定義はそれぞれ順番に処理されるので、未定義でエラーになる

- 定義は同時に起こるべきなので 7 になり正常

どっちが正しいかという問題4.19 、 確かに定義は同時に起こる

っていう意見も正しい気がする。

欄外のコラムでは「同時に起こるべきだけど、実装が難しいので現実的にはエラーかな」とある。

define式をletrecに展開し、変数のスコープをはっきりさせる例もあった


(define a <exp1>)
(define b <exp2>)
(a (b 123))


(let ((a null) (b null))
  (set! a <exp1>)
  (set! b <exp2>)
  (a (b 123)))

に変換すれば、exp1とexp2がそれぞれを参照できる。あと評価がlambda式等で遅延されてれば問題無い?


;;問 4.20 letrecをletを利用したマクロで実装する ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;let を lambda に展開する
(define-syntax let
  (syntax-rules ()
    ((let ((_k _v) ...) _b ...)
     ((lambda (_k ...) _b ...) _v ...))))

;;letrec を let と set! に展開する。局所変数の評価タイミングがset!時に変わるので
;;相互に参照する場合等上手くいく、のかな。。
(define-syntax letrec
  (syntax-rules ()
    ((letrec ((var1 init1)) body ...)
     ((lambda (var1)
        (let ((temp1 "undefined"))
          (set! temp1 var1)
          body ...)) init1))
    ((letrec ((var1 init1) params ...) body ...)
     (letrec (params ...)
       ((lambda (var1)
          (let ((temp1 "undefined"))
            (set! temp1 var1)
            body ...)) init1)))))

;;問 4.21 lambdaだけで再帰手続きを実装する ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;defineを利用せず(無名関数で)再帰処理を行う

;;define;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (fact n)
  (if (= n 1)
      1
      (* n (fact (- n 1)))))

(fact 10)

;;lambda;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
((lambda (n)
   ((lambda (fact)
      (fact fact n))
    (lambda (f k)
      (if (= k 1)
          1
          (* k (f f (- k 1)))))))
 10)

;;YCombinator化;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;こんな形にしたい
(define fact-maker
  (lambda (proc)
    (lambda (n)
      (if (= n 1)
          1
          (* n ((proc proc) (- n 1)))))))

(print ((fact-maker fact-maker) 8))

;;(proc proc) を追い出す
;;((proc proc) 5) は ((lambda (arg)((proc proc) arg)) 5) と等価なので
(define fact-maker2
  (lambda (proc)
    (lambda (n)
      (if (= n 1)
          1
          (* n
             ((lambda (arg)((proc proc) arg))
               (- n 1)))))))

(print ((fact-maker2 fact-maker2) 8))

;;(lambda (arg)((proc proc) arg)) を関数外に追い出す
(define fact-maker3
  (lambda (f)
    (lambda (n)
      (if (= n 1)
          1
          (* n
             (f (- n 1)))))))

;;を再帰的に実行したい。。
(lambda (proc)
  (fact-maker3
   (lambda (arg) ((proc proc) arg))))


;;factで利用したlambda式の使い方で
((lambda (proc)
   (fact-maker3
    (lambda (arg) ((proc proc) arg))))
 (lambda (proc)
   (fact-maker3
    (lambda (arg) ((proc proc) arg)))))


;;固有名を抜き出す
(lambda (f)
  ((lambda (proc)
     (f (lambda (arg) ((proc proc) arg))))
   (lambda (proc)
     (f (lambda (arg) ((proc proc) arg))))))


;;試してみる
(define Y
  (lambda (f)
    ((lambda (proc)
       (f (lambda (arg) ((proc proc) arg))))
     (lambda (proc)
       (f (lambda (arg) ((proc proc) arg)))))))

;;自分自身を受け取ることを期待する
(define fact_y
  (lambda (me)
    (lambda (n)
      (if (= n 1)
          1
          (* n (me (- n 1)))))))

(print
 ((Y fact_y) 8))

;;参考にしました。
;;http://www.loveruby.net/ja/misc/ycombinator.html

lambda式だけで再帰手続きをする、は面白かった。

なるほど、、自分自身を実行するために、引数に入れて続ければ良いのか。

うーん、syntax-ruleを実装してて時間が掛かった。 "..." は単純な可変長引数のような物かと思ってたら、誤解してた

もう少し高度なパターンマッチのシンボルだったのか。

まだマクロ内と実行時のシンボルの衝突が解決できてない気がするけど、まあいいや。次に進もう。

DellDell2012/01/10 09:09Normlaly I'm against killing but this article slaughtered my ignorance.

wutcwpiwutcwpi2012/01/10 19:50kheObL <a href="http://dxtxlvctfdbe.com/">dxtxlvctfdbe</a>

ikpwrvikpwrv2012/01/11 00:449NFH2Z , [url=http://brxakccahajj.com/]brxakccahajj[/url], [link=http://tgkrbfylyuqa.com/]tgkrbfylyuqa[/link], http://relikozwphgs.com/

rehgaqcsarehgaqcsa2012/01/12 23:27kq0Stw <a href="http://tieyaqwknxqx.com/">tieyaqwknxqx</a>

DeloresDelores2016/05/11 01:36Merci pour cet article qui m’a fait découvrir ce photographe qui joue savamment avec les couleurs. Je connaissais déjà le festival de Perpignan, et ça me donne encore plus envie d’y aller un jo&83#r2u0;Bonne journée

JennisJennis2016/05/11 19:37Mama por Dios deje de darle ilusiones al chino hombre no hay derecho, la gente hace tonterias por amor, eso lo debe saber usted que ve mas de una novela y se sabe mas de un <a href="http://psgazvhv.com">chi.me...sJugar</a> con la gente no esta bien, por mas pequeña que sea ;)

トラックバック - http://sicp.g.hatena.ne.jp/tkmr2000/20090314
 |