ものまね鳥。論理鳥。
鳥(コンビネータ)を全て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
もっとよいやり方があるのかもしれないが。
なかなか楽しい。