syrup/fun-utils.lisp
2025-04-14 15:36:00 -04:00

23 lines
988 B
Common Lisp

(in-package #:syrup)
(defmacro curry ((fun &rest args) &key (blank '*) (rest nil))
"Construct a lambda around FUN, where arguments not marked with * are pre-filled with the specified forms.
e.g. (curry (- * 2)) => (lambda (x) (- x 2))
:BLANK (default *) - specify the blank symbol
:REST (default NIL) - if true, add a &rest argument to the end of the lambda"
(let ((outer-args nil) (inner-args nil))
(dolist (arg args)
(if (eql arg blank)
(let ((sym (gensym)))
(push sym outer-args)
(push sym inner-args))
;; else
(push arg inner-args)))
;; reverse the lists, since we used PUSH to build them
(setf outer-args (nreverse outer-args)
inner-args (nreverse inner-args))
;; now create the lambda
(if rest
(let ((rest-sym (gensym)))
`(lambda (,@outer-args &rest ,rest-sym) (apply (function ,fun) ,@inner-args ,rest-sym)))
`(lambda ,outer-args (,fun ,@inner-args)))))