Posts tagged: scheme

Haskell-style curry function in Scheme

#lang racket

(define (>curry f . n-opt)
  (let loop ((final-args '()) 
             (n (if (empty? n-opt) 2 (car n-opt))))
    (if (zero? n)
        (apply f final-args)
        (lambda nth-args
          (loop (append final-args nth-args) (sub1 n))))))

(>curry list 0)                      ;=> '() ;; should this case really be…
((>curry list 1) 'a)                 ;=> '(a)
(((>curry list) 'a 'b 'c) 'd 'e 'f)  ;=> '(a b c d e f)
((((>curry list 3) 'a 1) 'b 2) 'c 3) ;=> '(a 1 b 2 c 3)

(define (curry< f . n-opt)
  (let loop ((final-args '()) 
             (n (if (empty? n-opt) 2 (car n-opt))))
    (if (zero? n)
        (apply f final-args)
        (lambda nth-args
          (loop (append nth-args final-args) (sub1 n))))))

(curry< list 0)                      ;=> '() ;; …part of the interface, though?
((curry< list 1) 'a)                 ;=> '(a)
(((curry< list) 'a 'b 'c) 'd 'e 'f)  ;=> '(d e f a b c)
((((curry< list 3) 'a 1) 'b 2) 'c 3) ;=> '(c 3 b 2 a 1)

#lang racket

;; This defines an n-argument version of the Y combinator. A use case is
;; implementing mutually recursive functions. The intended usage is:

;;   ((y* (lambda (f1 f2 ... fn) (lambda <body of f1>))
;;        (lambda (f1 f2 ... fn) (lambda <body of f2>))
;;        ...
;;        (lambda (f1 f2 ... fn) (lambda <body of fn>)))
;;    (lambda (f1 f2 ... fn) <use of f1 to fn>))

;; Implementation:

(define u (lambda (f) (f f)))           ;trusty old Mockingbird
(define y*
  (lambda fs
    (u (lambda (this)
         (lambda (receiver)
           (apply receiver
                  (map (lambda (f)
                         (lambda args
                           (apply ((u this) f) args)))
                       fs)))))))

;; An application: mutually recursive odd?/even? predicates

((y* (lambda (oddp evenp) (lambda (n) (if (zero? n) #f (evenp (sub1 n)))))
     (lambda (oddp evenp) (lambda (n) (if (zero? n) #t (oddp (sub1 n))))))
 (lambda (oddp evenp)
   (list (oddp 5) (oddp 6) (evenp 7) (evenp 8))))

;; produces '(#t #f #f #t)