Skip to content

Instantly share code, notes, and snippets.

@ha2ne2
Last active October 25, 2019 18:35
Show Gist options
  • Save ha2ne2/dc2c08ce212c3c7af372bf8cbbd861b8 to your computer and use it in GitHub Desktop.
Save ha2ne2/dc2c08ce212c3c7af372bf8cbbd861b8 to your computer and use it in GitHub Desktop.
Clojureでラムダ計算
;; 2019-10-26
;;;; 関数をカリー化して定義します。
;; (defn-c add [a b] (+ a b)) が
;; (def add (fn [a] (fn [b] (+ a b)))) になります。
(defmacro defn-c [fn-name args body]
`(def ~fn-name (fn-c ~args ~body)))
(defmacro fn-c [[x & xs :as args] body]
(if (empty? args)
body
`(fn [~x]
(fn-c ~xs ~body))))
(defn-c one [f x] (f x))
(defn-c two [f x] (f (f x)))
(defn-c three [f x] (f (f (f x))))
(defn-c add [n m f x] ((n f) ((m f) x)))
(defn-c mul [n m f x] ((n (m f)) x))
(defn-c pow [n m f x] (((m n) f) x))
(defn-c dec' [n f x] (((n (fn-c [g h] (h (g f)))) (constantly x)) identity))
(defn decode [n] ((n inc) 0))
(decode ((add one) two)) ;=> 3
(decode ((mul three) two)) ;=> 6
(decode ((pow three) two)) ;=> 9
(decode (dec' ((pow three) two))) ;=> 8
;;;;;;;; 適用の所がちょっとあれなのでマクロを使ってもう一歩進めてみる。
;;;; 式をHaskellみたいな感じに評価します。
;; (<- a b c d) が
;; (((a b) c) d) になります。
;; 再帰的に適用するので
;; (<- a b c d (e f g)) は
;; (((a b) c) d ((e f) g) になります。
(defmacro <- [& lst]
`(<-% ~(reverse lst)))
(defmacro <-% [[x & xs]]
(cond (empty? xs) x
(list? x) (list `(<-% ~xs) `(<-% ~(reverse x)))
:else (list `(<-% ~xs) x)))
(defn-c add [n m f x] (<- n f (m f x)))
(defn-c mul [n m f x] (<- n (m f) x))
(defn-c pow [n m f x] (<- m n f x))
(def-c dec' [n f x]
(let [hoge (fn-c [g h] (h (g f)))]
(<- n hoge (constantly x) identity))) ;; <-が再帰的なのでletしないといけない。びみょう。
(decode (<- add one two)) ;=> 3
(decode (<- mul three two)) ;=> 6
(decode (<- pow three two)) ;=> 9
(decode (<- dec' (pow three two))) ;=> 8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment