ものまね鳥。論理鳥。

鳥(コンビネータ)を全て1引数の関数として実装して、schemeで動かそうとすると、どうしても余計に(主観だけど)括弧がついてしまう。

(define I (lambda (x) x))
(define K (lambda (x) (lambda (y) x)))
(define T (lambda (x)
           (lambda (y) (y x))))
(define C (lambda (x)
           (lambda (y)
             (lambda (z) ((x z) y)))))
(define V (lambda (x)
           (lambda (y)
              (lambda (z) ((z x) y)))))
(define R (lambda (x)
           (lambda (y)
             (lambda (z) ((y z) x)))))
(define S (lambda (x)
           (lambda (y)
             (lambda (z) ((x z) (y z))))))

(define t K)   ;; true!  if-then だね。
(define f (K I))  ;; false! if-elseだね。
(define NOT ((V f) t))
(define AND (R f))
(define OR (T t))
(define CONSEQUENCE (R t))
(define EQ ((C S) NOT))

(define (decode_b b) (if ((b #t) #f) 'true 'false))

;; AND 実行
(decode_b ((AND t) f)) ;; => false

この ((AND t) f) を
(AND t f) と書きたくなったので、色々試行錯誤するうち、初めてマクロを使ってみたら上手く行った。

;; 考え。
;; (a b c d)というリストを (((a b) c) d) のように変形して、そのまま実行したい
;;
;; 変形
;; (a b c d) -> (d c b a) ;; 逆転 
;;  -> (d (c (b a)))      ;; 入れ子にする。
;;  -> (((a b) c) d)      ;; 再び逆転
(use util.match)
(define l2 (match-lambda
                 [(? symbol? a) a]
                 [((? symbol? a)) a]
                 [((? symbol? a) (? symbol? b)) `(,a ,b)]
                 [(a b) `(,(l2 a) ,(l2 b))]
                 [(a b . c) `(,(l2 a) ,(l2 `(,b ,c)))]))
 
(define (reverse-all-itr l acc)
  (cond ((null? l) acc)
                ((pair? (car l))
                 (reverse-all-itr (cdr l) (cons (reverse-all-itr (car l) '()) acc)))
                (else
                 (reverse-all-itr (cdr l) (cons (car l)acc) ))))

(define (nest-list l)
  (reverse-all-itr (l2 (reverse-all-itr l '())) '()))

(define-macro check-bool! (lambda (vars) (let ((evaled-exp (nest-list vars))) `(decode_b ,evaled-exp))))

(check-bool! (AND t t)) ;; -> true
(check-bool! (AND t f)) ;; -> false
(check-bool! (AND f t)) ;; -> false
(check-bool! (AND f f)) ;; -> false

もっとよいやり方があるのかもしれないが。

なかなか楽しい。