« schelogと%macroexpand | Main | 今日の日記 »

2007.09.02

schelog その3

Schemeで動くロジックプログラミングの勉強続き

こういうルールに対して、
(define %knows-simple
  (%rel ()
     [('Odysseus 'Tex)]))
        

(%which () (%knows-simple 'Odysseus 'Tex))が()trueを返し、(%which () (%knows-simple 'Odysseus 'Scheme))が#fを返す所を追おう。

まずはマクロを展開する。
(%macroexpand (%which () (%knows-simple 'Odysseus 'Tex)))

展開するとこんな感じ。


(let ()
  (call-with-current-continuation
   (lambda (__qk)
     (set! schelog:*more-k* __qk)
     (set! schelog:*more-fk*
           ((schelog:deref* (%knows-simple 'Odysseus 'Tex))
            (lambda (d)
              (set! schelog:*more-fk* #f)
              (schelog:*more-k* #f))))
     (schelog:*more-k*
      (map
       (lambda (nam val)
         (list nam (schelog:deref* val)))
       '()
       (list))))))

(%which () (%knows-simple 'Odysseus 'Tex))の一つめの引数が()なので、letは意味が無くて、これと等価。

(call-with-current-continuation (lambda (__qk)
   (set! schelog:*more-k* __qk)   ; ここで、継続をschelog:*more-k*に代入
   (set! schelog:*more-fk*      ;  なんか処理した結果をschelog:*more-fk*に代入
     ((schelog:deref* (%knows-simple 'Odysseus 'Tex))
       (lambda (d)
         (set! schelog:*more-fk* #f)
         (schelog:*more-k* #f))))
   ; 下のmapで処理した結果を、schelog:*more-k*に渡す。  
   ; schelog:*more-k* が継続 __qk なので、mapの結果がそのまま%whichの戻り値になる。
   (schelog:*more-k*      
    (map (lambda (nam val) (list nam (schelog:deref* val))) '() (list)) ;;ここまでmap処理
     )))

どうも、したのmap処理を実行した形跡が()っぽい。mapの引数の評価順序は決まっていないが、gaucheとこの関数の場合、2つの目の引数が空リストなのでmapの中のlambda式は評価されずに'()を返している。

ちょっと話が楽になって
(call-with-current-continuation (lambda (__qk)
   (set! schelog:*more-k* __qk)   ; ここで、継続をschelog:*more-k*に代入
   (set! schelog:*more-fk*      ;  なんか処理した結果をschelog:*more-fk*に代入
      ((schelog:deref* (%knows-simple 'Odysseus 'Tex))
        (lambda (d)
         (set! schelog:*more-fk* #f)
         (schelog:*more-k* #f))))
   (schelog:*more-k* '()    ; ここに処理が移ると()trueを返す。
     )))

2つめのset!で、マッチングに成功したらそのまま抜けて、失敗したら一番奥のlambdaを評価する。その結果、schelog:*more-fk*に#fをset!し、(schelog:*more-k* #f)を評価して脱出している。schelog:*more-k*が最初に渡された継続だから、これで一気に#fを返す。

(set! schelog:*more-fk*        
   ((schelog:deref* (%knows-simple 'Odysseus 'Tex))
     (lambda (d)
      (set! schelog:*more-fk* #f)
      (schelog:*more-k* #f))))


schelog:deref*は、(%knows-simple 'Odysseus 'Tex)の戻り値をそのまま使っている。ようやく真偽の判定が、%=にある所まで追い込む。今の段階では、リストが同じかどうかを判断しているだけみたい。

(%=  '(Odysseus Tex) (list 'Odysseus 'Tex))

とりあえずここ。試しに、元のサンプルを展開したらこんな感じに。


(%macroexpand 
  (%rel ()
        [('Odysseus 'Tex)]
        [('Odysseus 'Prolog)]
        [('Odysseus 'Scheme)]
        [('Odysseus 'Panelope)]
        [('Panelope 'Tex)]
        [('Panelope 'Prolog)]
        [('Panelope 'Odysseus)]
        [('Telemachus 'Tex)]
        [('Telemachus 'calculus)]
        ))
 


(lambda __fmls
  (lambda (__fk)
    (call-with-current-continuation
     (lambda (__sk)
       (let ((! (lambda (fk1) __fk)))
         (%let
          ()
          (call-with-current-continuation
           (lambda #0=(__fk)
            (let* ((__fk ((%= __fmls (list 'Odysseus 'Tex)) . #1=(__fk)))) . #2=((__sk __fk)))))
          (call-with-current-continuation
           (lambda #0#
             (let* ((__fk ((%= __fmls (list 'Odysseus 'Prolog)) . #1#))) . #2#)))
          (call-with-current-continuation
           (lambda #0# (let* ((__fk ((%= __fmls (list 'Odysseus 'Scheme)) . #1#))) . #2#)))
          (call-with-current-continuation
           (lambda #0# (let* ((__fk ((%= __fmls (list 'Odysseus 'Panelope)) . #1#))) . #2#)))
          (call-with-current-continuation
           (lambda #0# (let* ((__fk ((%= __fmls (list 'Panelope 'Tex)) . #1#))) . #2#)))
          (call-with-current-continuation
           (lambda #0# (let* ((__fk ((%= __fmls (list 'Panelope 'Prolog)) . #1#))) . #2#)))
          (call-with-current-continuation
           (lambda #0# (let* ((__fk ((%= __fmls (list 'Panelope 'Odysseus)) . #1#))) . #2#)))
          (call-with-current-continuation
           (lambda #0# (let* ((__fk ((%= __fmls (list 'Telemachus 'Tex)) . #1#))) . #2#)))
          (call-with-current-continuation
           (lambda #0# (let* ((__fk ((%= __fmls (list 'Telemachus 'calculus)) . #1#))) . #2#)))
          (__fk 'fail)))))))

(call/cc (labmda ・・・))が全て、let%の引数になっている。
とりあえず、ルールが一個しか無いような場合は、同じリストが存在するかだけで判断できる。って、ものすごい遠回りして気がついた。自分がアホすぎて泣けてくる。ここまで整理してみてルールの連鎖に入ろう。

|

« schelogと%macroexpand | Main | 今日の日記 »

Comments

Post a comment



(Not displayed with comment.)




TrackBack

TrackBack URL for this entry:
http://app.cocolog-nifty.com/t/trackback/18154/16318771

Listed below are links to weblogs that reference schelog その3:

« schelogと%macroexpand | Main | 今日の日記 »