リストのカリー化

(a b c d)というリストが与えられたら、(((a b) c) d)というリストに変換する関数とその逆をする関数を作ってみた。
カリー化すると必ず2要素のリストになるので、リストの構造的には、(((a . b) . c) . d)にする方が無駄がないのかもしれないけど、個人的好みにより前者を採用。

(use util.match)

(define (curry l)
  (if (pair? l) (currys (reverse l)) l))
(define currys (match-lambda
  ((x)                      (curry x))
  ((x . xs) `(,(currys xs) ,(curry x)))))

(define (uncurry l)
  (if (pair? l) (uncurrys l) l))
(define uncurrys (match-lambda
  ((xs x) `(,@(uncurrys xs) ,(uncurry x)))
  (    x  `(                ,(uncurry x)))))

#?=(uncurry #?=(curry #?='(a b c d)))
#?=(uncurry #?=(curry #?='(a b c (a b c) a b c)))

実行結果

#?-    (a b c d)
#?-    (((a b) c) d)
#?-    (a b c d)

#?-    (a b c (a b c) a b c)
#?-    ((((((a b) c) ((a b) c)) a) b) c)
#?-    (a b c (a b c) a b c)